feat: add tool_choice to dialectic level settings, fix: `extra-high` label to `max` (#326)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
817123de95
commit
26da24c8bf
|
|
@ -147,14 +147,14 @@ LLM_ANTHROPIC_API_KEY=your-anthropic-api-key-here
|
|||
# DIALECTIC_LEVELS__high__THINKING_BUDGET_TOKENS=0
|
||||
# DIALECTIC_LEVELS__high__MAX_TOOL_ITERATIONS=4
|
||||
|
||||
# Extra-high level
|
||||
# DIALECTIC_LEVELS__extra-high__PROVIDER=anthropic
|
||||
# DIALECTIC_LEVELS__extra-high__MODEL=claude-opus-4-5
|
||||
# DIALECTIC_LEVELS__extra-high__THINKING_BUDGET_TOKENS=512
|
||||
# DIALECTIC_LEVELS__extra-high__MAX_TOOL_ITERATIONS=10
|
||||
# Max level
|
||||
# DIALECTIC_LEVELS__max__PROVIDER=anthropic
|
||||
# DIALECTIC_LEVELS__max__MODEL=claude-opus-4-5
|
||||
# DIALECTIC_LEVELS__max__THINKING_BUDGET_TOKENS=512
|
||||
# DIALECTIC_LEVELS__max__MAX_TOOL_ITERATIONS=10
|
||||
# Optional backup per level (must set both or neither):
|
||||
# DIALECTIC_LEVELS__extra-high__BACKUP_PROVIDER=google
|
||||
# DIALECTIC_LEVELS__extra-high__BACKUP_MODEL=gemini-2.5-pro
|
||||
# DIALECTIC_LEVELS__max__BACKUP_PROVIDER=google
|
||||
# DIALECTIC_LEVELS__max__BACKUP_MODEL=gemini-2.5-pro
|
||||
|
||||
# =============================================================================
|
||||
# Summary Settings
|
||||
|
|
|
|||
|
|
@ -121,10 +121,10 @@ jobs:
|
|||
DIALECTIC_LEVELS__high__MODEL: test
|
||||
DIALECTIC_LEVELS__high__THINKING_BUDGET_TOKENS: 0
|
||||
DIALECTIC_LEVELS__high__MAX_TOOL_ITERATIONS: 4
|
||||
DIALECTIC_LEVELS__extra-high__PROVIDER: openai
|
||||
DIALECTIC_LEVELS__extra-high__MODEL: test
|
||||
DIALECTIC_LEVELS__extra-high__THINKING_BUDGET_TOKENS: 0
|
||||
DIALECTIC_LEVELS__extra-high__MAX_TOOL_ITERATIONS: 10
|
||||
DIALECTIC_LEVELS__max__PROVIDER: openai
|
||||
DIALECTIC_LEVELS__max__MODEL: test
|
||||
DIALECTIC_LEVELS__max__THINKING_BUDGET_TOKENS: 0
|
||||
DIALECTIC_LEVELS__max__MAX_TOOL_ITERATIONS: 10
|
||||
DIALECTIC_QUERY_GENERATION_PROVIDER: openai
|
||||
DIALECTIC_QUERY_GENERATION_MODEL: test
|
||||
SUMMARY_PROVIDER: openai
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ MODEL = "claude-opus-4-5"
|
|||
THINKING_BUDGET_TOKENS = 0
|
||||
MAX_TOOL_ITERATIONS = 4
|
||||
|
||||
[dialectic.levels.extra-high]
|
||||
[dialectic.levels.max]
|
||||
PROVIDER = "anthropic"
|
||||
MODEL = "claude-opus-4-5"
|
||||
THINKING_BUDGET_TOKENS = 512
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ authors = [
|
|||
{ name = "Plastic Labs", email = "hello@plasticlabs.ai" },
|
||||
]
|
||||
dependencies = [
|
||||
"honcho-core==1.10.0",
|
||||
"honcho-core==1.11.0",
|
||||
"httpx>=0.28.0, <1",
|
||||
"pydantic>=2.0.0, <3",
|
||||
"typing-extensions>=4.12.0; python_version < \"3.12\"",
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ class AsyncPeer(PeerBase):
|
|||
stream: bool = False,
|
||||
target: str | PeerBase | None = None,
|
||||
session: str | SessionBase | None = None,
|
||||
reasoning_level: Literal["minimal", "low", "medium", "high", "extra-high"]
|
||||
reasoning_level: Literal["minimal", "low", "medium", "high", "max"]
|
||||
| None = None,
|
||||
) -> str | DialecticStreamResponse | None:
|
||||
"""
|
||||
|
|
@ -166,7 +166,7 @@ class AsyncPeer(PeerBase):
|
|||
information from that session is considered. Can be a session
|
||||
ID string or an AsyncSession object.
|
||||
reasoning_level: Optional reasoning level for the query: "minimal", "low", "medium",
|
||||
"high", or "extra-high". Defaults to "low" if not provided.
|
||||
"high", or "max". Defaults to "low" if not provided.
|
||||
|
||||
Returns:
|
||||
For non-streaming: Response string containing the answer, or None if no relevant information
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ class Peer(PeerBase):
|
|||
stream: bool = False,
|
||||
target: str | PeerBase | None = None,
|
||||
session: str | SessionBase | None = None,
|
||||
reasoning_level: Literal["minimal", "low", "medium", "high", "extra-high"]
|
||||
reasoning_level: Literal["minimal", "low", "medium", "high", "max"]
|
||||
| None = None,
|
||||
) -> str | DialecticStreamResponse | None:
|
||||
"""
|
||||
|
|
@ -143,7 +143,7 @@ class Peer(PeerBase):
|
|||
information from that session is considered. Can be a session
|
||||
ID string or a Session object.
|
||||
reasoning_level: Optional reasoning level for the query: "minimal", "low", "medium",
|
||||
"high", or "extra-high". Defaults to "low" if not provided.
|
||||
"high", or "max". Defaults to "low" if not provided.
|
||||
|
||||
Returns:
|
||||
For non-streaming: Response string containing the answer, or None if no relevant information
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
"": {
|
||||
"name": "@honcho-ai/sdk",
|
||||
"dependencies": {
|
||||
"@honcho-ai/core": "2.1.0",
|
||||
"@honcho-ai/core": "2.2.0",
|
||||
"@types/node": "^24.0.1",
|
||||
"zod": "4.0.0",
|
||||
},
|
||||
|
|
@ -106,7 +106,7 @@
|
|||
|
||||
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.3.8", "", { "os": "win32", "cpu": "x64" }, "sha512-RguzimPoZWtBapfKhKjcWXBVI91tiSprqdBYu7tWhgN8pKRZhw24rFeNZTNf6UiBfjCYCi9eFQs/JzJZIhuK4w=="],
|
||||
|
||||
"@honcho-ai/core": ["@honcho-ai/core@2.1.0", "", { "dependencies": { "@types/node": "^18.11.18", "@types/node-fetch": "^2.6.4", "abort-controller": "^3.0.0", "agentkeepalive": "^4.2.1", "form-data-encoder": "1.7.2", "formdata-node": "^4.3.2", "node-fetch": "^2.6.7" } }, "sha512-BssURYjiBmFF/guQQkr6Dpiz1ZOzhJsf/rdp6Ek/A3T2vNz3pop0fNgHK6SjCFcqjSKF8SHWJMF2VqqH0y4J6Q=="],
|
||||
"@honcho-ai/core": ["@honcho-ai/core@2.2.0", "", { "dependencies": { "@types/node": "^18.11.18", "@types/node-fetch": "^2.6.4", "abort-controller": "^3.0.0", "agentkeepalive": "^4.2.1", "form-data-encoder": "1.7.2", "formdata-node": "^4.3.2", "node-fetch": "^2.6.7" } }, "sha512-3lDBdruXlg2m8OEGe5mSD6pt4EgZulgvT0tbaM7k61Mi+m8H56aQNzlCv5yPLdw5G/FIEjyJJcFfHknqdxoyrg=="],
|
||||
|
||||
"@istanbuljs/load-nyc-config": ["@istanbuljs/load-nyc-config@1.1.0", "", { "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", "get-package-type": "^0.1.0", "js-yaml": "^3.13.1", "resolve-from": "^5.0.0" } }, "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ=="],
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
"test:coverage": "jest --coverage"
|
||||
},
|
||||
"dependencies": {
|
||||
"@honcho-ai/core": "2.1.0",
|
||||
"@honcho-ai/core": "2.2.0",
|
||||
"@types/node": "^24.0.1",
|
||||
"zod": "4.0.0"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ export class Peer {
|
|||
* information from that session is considered. Can be a session
|
||||
* ID string or a Session object.
|
||||
* @param reasoningLevel - Optional reasoning level for the query: "minimal", "low", "medium",
|
||||
* "high", or "extra-high". Defaults to "low" if not provided.
|
||||
* "high", or "max". Defaults to "low" if not provided.
|
||||
* @returns Promise resolving to:
|
||||
* - For non-streaming: response string or null if no relevant information
|
||||
* - For streaming: DialecticStreamResponse that can be iterated over
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ export const ChatQuerySchema = z.object({
|
|||
val ? (typeof val === 'string' ? val : val.id) : undefined
|
||||
),
|
||||
reasoningLevel: z
|
||||
.enum(['minimal', 'low', 'medium', 'high', 'extra-high'])
|
||||
.enum(['minimal', 'low', 'medium', 'high', 'max'])
|
||||
.optional(),
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -286,13 +286,13 @@ class PeerCardSettings(HonchoSettings):
|
|||
|
||||
|
||||
# Reasoning levels for dialectic - defined here to avoid circular imports with schemas
|
||||
ReasoningLevel = Literal["minimal", "low", "medium", "high", "extra-high"]
|
||||
ReasoningLevel = Literal["minimal", "low", "medium", "high", "max"]
|
||||
REASONING_LEVELS: list[ReasoningLevel] = [
|
||||
"minimal",
|
||||
"low",
|
||||
"medium",
|
||||
"high",
|
||||
"extra-high",
|
||||
"max",
|
||||
]
|
||||
|
||||
|
||||
|
|
@ -313,6 +313,9 @@ class DialecticLevelSettings(BaseModel):
|
|||
MAX_TOOL_ITERATIONS: Annotated[
|
||||
int, Field(ge=0, le=50, validation_alias="max_tool_iterations")
|
||||
]
|
||||
TOOL_CHOICE: Annotated[str | None, Field(validation_alias="tool_choice")] = (
|
||||
None # None/auto lets model decide, "any"/"required" forces tool use
|
||||
)
|
||||
|
||||
@model_validator(mode="after")
|
||||
def _validate_backup_configuration(self) -> "DialecticLevelSettings":
|
||||
|
|
@ -350,7 +353,8 @@ class DialecticSettings(HonchoSettings):
|
|||
PROVIDER="google",
|
||||
MODEL="gemini-2.5-flash-lite",
|
||||
THINKING_BUDGET_TOKENS=0,
|
||||
MAX_TOOL_ITERATIONS=2,
|
||||
MAX_TOOL_ITERATIONS=5,
|
||||
TOOL_CHOICE="any",
|
||||
),
|
||||
"low": DialecticLevelSettings(
|
||||
PROVIDER="google",
|
||||
|
|
@ -370,7 +374,7 @@ class DialecticSettings(HonchoSettings):
|
|||
THINKING_BUDGET_TOKENS=0,
|
||||
MAX_TOOL_ITERATIONS=4,
|
||||
),
|
||||
"extra-high": DialecticLevelSettings(
|
||||
"max": DialecticLevelSettings(
|
||||
PROVIDER="anthropic",
|
||||
MODEL="claude-opus-4-5",
|
||||
THINKING_BUDGET_TOKENS=2048,
|
||||
|
|
|
|||
|
|
@ -347,7 +347,7 @@ class DialecticAgent:
|
|||
prompt="", # Ignored since we pass messages
|
||||
max_tokens=settings.DIALECTIC.MAX_OUTPUT_TOKENS,
|
||||
tools=DIALECTIC_TOOLS,
|
||||
tool_choice=None,
|
||||
tool_choice=level_settings.TOOL_CHOICE,
|
||||
tool_executor=tool_executor,
|
||||
max_tool_iterations=level_settings.MAX_TOOL_ITERATIONS,
|
||||
messages=self.messages,
|
||||
|
|
@ -401,7 +401,7 @@ class DialecticAgent:
|
|||
stream=True,
|
||||
stream_final_only=True,
|
||||
tools=DIALECTIC_TOOLS,
|
||||
tool_choice=None,
|
||||
tool_choice=level_settings.TOOL_CHOICE,
|
||||
tool_executor=tool_executor,
|
||||
max_tool_iterations=level_settings.MAX_TOOL_ITERATIONS,
|
||||
messages=self.messages,
|
||||
|
|
|
|||
|
|
@ -653,7 +653,7 @@ class DialecticOptions(BaseModel):
|
|||
stream: bool = False
|
||||
reasoning_level: ReasoningLevel = Field(
|
||||
default="low",
|
||||
description="Level of reasoning to apply: minimal, low, medium, high, or extra-high",
|
||||
description="Level of reasoning to apply: minimal, low, medium, high, or max",
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
8
uv.lock
8
uv.lock
|
|
@ -859,7 +859,7 @@ dev = [
|
|||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "honcho-core", specifier = "==1.10.0" },
|
||||
{ name = "honcho-core", specifier = "==1.11.0" },
|
||||
{ name = "httpx", specifier = ">=0.28.0,<1" },
|
||||
{ name = "pydantic", specifier = ">=2.0.0,<3" },
|
||||
{ name = "typing-extensions", marker = "python_full_version < '3.12'", specifier = ">=4.12.0" },
|
||||
|
|
@ -870,7 +870,7 @@ dev = [{ name = "ruff", specifier = ">=0.11.13" }]
|
|||
|
||||
[[package]]
|
||||
name = "honcho-core"
|
||||
version = "1.10.0"
|
||||
version = "1.11.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "anyio" },
|
||||
|
|
@ -880,9 +880,9 @@ dependencies = [
|
|||
{ name = "sniffio" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/6c/5f/912716e911966d8cefb34a23f9b3a452348f147e040c1025113a202363a2/honcho_core-1.10.0.tar.gz", hash = "sha256:1dc139f6199a7589781636b4535cc97da6016477fbaeeaee53376e7a227a5c51", size = 144284, upload-time = "2026-01-12T23:30:30.87Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/1b/82/7c7db37556930ecb9b908f911100159abc46e103aa252b3ec318c720b413/honcho_core-1.11.0.tar.gz", hash = "sha256:2898b18633930cda6d8414c7e001e4cb9da17327f448000a6c312b51372975f3", size = 144331, upload-time = "2026-01-13T19:53:59.582Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/63/27/7cc9c5d0a91921339b843bed3d520225731199156c3410604375e5faf487/honcho_core-1.10.0-py3-none-any.whl", hash = "sha256:d0c7a1285b8e75c106b540773c0077e563c9bf6abda040da583bb7566828877d", size = 138588, upload-time = "2026-01-12T23:30:29.351Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ad/08/4ada41526b74b11a332db0e48d75f4d93b4ed474d82a48c7251d78656dce/honcho_core-1.11.0-py3-none-any.whl", hash = "sha256:519c6a7759badfae1b1a3587fbf577cb5ab8188e5093dc0f4fd62602e8dfb523", size = 138588, upload-time = "2026-01-13T19:53:58.369Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
|||
Loading…
Reference in New Issue