mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
Scale skill metadata budgets with model context windows (#34626)
## Why A fixed character limit does not account for the different context-window sizes supported by models. ## What changed - Budget extension-rendered skill metadata at 2% of the resolved model context window, capped at 4,000 tokens. - Keep the existing 8,000-character fallback when model context metadata is unavailable. - Include the omission marker in the budget and still emit it when no skill entry fits. - Apply the same resolved budget to executor and host skill catalogs assembled for a turn. ## Testing - Cover proportional and capped budgets, multibyte fallback accounting, and omission-marker behavior. - Verify through the production turn path that larger model context windows include more catalog entries without exceeding the computed budget. GitOrigin-RevId: 4667293f1594de4dd605b32b9fa4255d26772c0f
This commit is contained in:
1 parent
bbad09a83b
commit
37eef7bacc
10 files changed
+454
-31
No files matched your search
@@ -35,12 +35,14 @@ fn description_selection_follows_render_policy() {
|
||||
&catalog,
|
||||
/*include_skills_usage_instructions*/ false,
|
||||
SkillCatalogRenderPolicy::CoreCompatible,
|
||||
SkillMetadataBudget::Characters(8_000),
|
||||
)
|
||||
.expect("catalog should render");
|
||||
let extension = available_skills_fragment(
|
||||
&catalog,
|
||||
/*include_skills_usage_instructions*/ false,
|
||||
SkillCatalogRenderPolicy::ExtensionCompatible,
|
||||
SkillMetadataBudget::Characters(8_000),
|
||||
)
|
||||
.expect("catalog should render");
|
||||
|
||||
@@ -65,3 +67,110 @@ fn description_selection_follows_render_policy() {
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn catalog_budget_uses_capped_context_percentage_or_character_fallback() {
|
||||
assert_eq!(
|
||||
capped_skill_metadata_budget(Some(100_000)),
|
||||
SkillMetadataBudget::Tokens(2_000)
|
||||
);
|
||||
assert_eq!(
|
||||
capped_skill_metadata_budget(Some(400_000)),
|
||||
SkillMetadataBudget::Tokens(4_000)
|
||||
);
|
||||
assert_eq!(
|
||||
capped_skill_metadata_budget(/*context_window*/ None),
|
||||
SkillMetadataBudget::Characters(8_000)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn omission_marker_is_charged_to_catalog_budget() {
|
||||
let catalog = SkillCatalog {
|
||||
entries: (0..20)
|
||||
.map(|index| {
|
||||
entry(
|
||||
&format!("skill-{index:02}"),
|
||||
"A description long enough to put the catalog under budget pressure.",
|
||||
/*short_description*/ None,
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
warnings: Vec::new(),
|
||||
};
|
||||
let fragment = available_skills_fragment(
|
||||
&catalog,
|
||||
/*include_skills_usage_instructions*/ false,
|
||||
SkillCatalogRenderPolicy::ExtensionCompatible,
|
||||
SkillMetadataBudget::Tokens(100),
|
||||
)
|
||||
.expect("catalog should render");
|
||||
let rendered_metadata_cost = fragment
|
||||
.body()
|
||||
.lines()
|
||||
.filter(|line| line.starts_with("- "))
|
||||
.map(|line| approx_token_count(&format!("{line}\n")))
|
||||
.sum::<usize>();
|
||||
|
||||
assert!(fragment.body().contains("additional skills omitted"));
|
||||
assert!(rendered_metadata_cost <= 100);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn character_fallback_counts_multibyte_metadata_by_characters() {
|
||||
let description = "💡".repeat(MAX_CATALOG_SKILL_DESCRIPTION_CHARS);
|
||||
let catalog = SkillCatalog {
|
||||
entries: vec![
|
||||
entry(
|
||||
"multibyte-one",
|
||||
&description,
|
||||
/*short_description*/ None,
|
||||
),
|
||||
entry(
|
||||
"multibyte-two",
|
||||
&description,
|
||||
/*short_description*/ None,
|
||||
),
|
||||
],
|
||||
warnings: Vec::new(),
|
||||
};
|
||||
|
||||
let fragment = available_skills_fragment(
|
||||
&catalog,
|
||||
/*include_skills_usage_instructions*/ false,
|
||||
SkillCatalogRenderPolicy::ExtensionCompatible,
|
||||
SkillMetadataBudget::Characters(8_000),
|
||||
)
|
||||
.expect("catalog should render");
|
||||
|
||||
assert!(fragment.body().contains("multibyte-one"));
|
||||
assert!(fragment.body().contains("multibyte-two"));
|
||||
assert!(!fragment.body().contains("additional skills omitted"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn catalog_emits_omission_marker_when_every_skill_exceeds_budget() {
|
||||
let catalog = SkillCatalog {
|
||||
entries: vec![entry(
|
||||
"oversized",
|
||||
&"x".repeat(MAX_CATALOG_SKILL_DESCRIPTION_CHARS),
|
||||
/*short_description*/ None,
|
||||
)],
|
||||
warnings: Vec::new(),
|
||||
};
|
||||
|
||||
let fragment = available_skills_fragment(
|
||||
&catalog,
|
||||
/*include_skills_usage_instructions*/ false,
|
||||
SkillCatalogRenderPolicy::ExtensionCompatible,
|
||||
SkillMetadataBudget::Tokens(100),
|
||||
)
|
||||
.expect("omission marker should fit");
|
||||
|
||||
assert!(!fragment.body().contains("- oversized:"));
|
||||
assert!(
|
||||
fragment
|
||||
.body()
|
||||
.contains("- 1 additional skill omitted from this bounded skills list.")
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user