fix(engine): teach the router with examples and pin its sampling

This commit is contained in:
Anthony Stirling
2026-09-02 09:57:53 +01:00
parent 2cf355c5cd
commit f57d0e2c81
2 changed files with 28 additions and 3 deletions
+1 -1
View File
@@ -12,7 +12,7 @@ STIRLING_FAST_MODEL=anthropic:claude-haiku-4-5
# Default output token limits applied by the engine for each model tier.
STIRLING_SMART_MODEL_MAX_TOKENS=8192
STIRLING_FAST_MODEL_MAX_TOKENS=2048
STIRLING_FAST_MODEL_MAX_TOKENS=4096
# Process-wide cap on concurrent model API calls, shared by both model tiers.
# Per-request fan-outs (chunked reasoner workers, contradiction detection) are
+27 -2
View File
@@ -7,6 +7,7 @@ from typing import Literal, assert_never
from pydantic import ConfigDict, Field
from pydantic_ai import Agent
from pydantic_ai.output import NativeOutput, ToolOutput
from pydantic_ai.settings import ModelSettings
from pydantic_ai.tools import RunContext
from stirling.agents.output_mode import output_retries, uses_tool_output
@@ -65,10 +66,34 @@ _ROUTER_SYSTEM_PROMPT = (
"- pdf_create: generate a NEW document from scratch (invoice, report, letter) - no input file.\n"
"- unsupported: none of the above fit, or the user asks about the assistant itself; put a "
"helpful message in 'message'.\n"
"Respond with the capability and (only for unsupported) a message."
"Respond with the capability and (only for unsupported) a message.\n"
"\n"
"Decide by what the user wants BACK, not by which PDF words appear in the message. "
"Wanting an answer, or information read out of the document, is pdf_question. Wanting a "
"changed file handed back is pdf_edit. A document being mentioned is not a request to act "
"on it.\n"
"\n"
"Examples:\n"
' "How long is the notice period?" -> pdf_question\n'
' "Shorten the notice period to 30 days" -> pdf_edit\n'
' "Is there a table of contents?" -> pdf_question\n'
' "Add a table of contents" -> pdf_edit\n'
' "Does it say anything about encryption?" -> pdf_question\n'
' "Encrypt this file" -> pdf_edit\n'
' "What sections cover the merger?" -> pdf_question\n'
' "Combine these into one file" -> pdf_edit\n'
' "Tell me if the numbers add up" -> pdf_question\n'
' "Put a note on every paragraph that needs work" -> pdf_review\n'
' "Build me a purchase order from scratch" -> pdf_create\n'
' "Make a rule that stamps every upload" -> user_spec\n'
' "Which version of the app is this?" -> unsupported'
)
def _router_model_settings(runtime: AppRuntime) -> ModelSettings:
return {**runtime.fast_model_settings, "temperature": 0.0}
class OrchestratorAgent:
def __init__(self, runtime: AppRuntime) -> None:
self.runtime = runtime
@@ -146,7 +171,7 @@ class OrchestratorAgent:
output_type=NativeOutput([_RouteDecision]),
retries=output_retries(runtime.settings.chat_provider),
system_prompt=_ROUTER_SYSTEM_PROMPT,
model_settings=runtime.fast_model_settings,
model_settings=_router_model_settings(runtime),
)
if self._route_via_enum
else None