Add namespace metadata to deriver LLM calls
This commit is contained in:
parent
bb6dad9157
commit
e88a59932a
|
|
@ -154,6 +154,7 @@ async def process_representation_tasks_batch(
|
|||
enable_retry=True,
|
||||
retry_attempts=3,
|
||||
trace_name="minimal_deriver",
|
||||
request_metadata={"namespace": settings.NAMESPACE},
|
||||
telemetry=LLMTelemetryContext(
|
||||
workspace_name=latest_message.workspace_name,
|
||||
call_purpose=CallPurpose.DERIVER_REPRESENTATION.value,
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ async def honcho_llm_call(
|
|||
trace_name: str | None = None,
|
||||
iteration_callback: IterationCallback | None = None,
|
||||
telemetry: LLMTelemetryContext | None = None,
|
||||
request_metadata: dict[str, str] | None = None,
|
||||
) -> HonchoLLMCallResponse[M]: ...
|
||||
|
||||
|
||||
|
|
@ -105,6 +106,7 @@ async def honcho_llm_call(
|
|||
trace_name: str | None = None,
|
||||
iteration_callback: IterationCallback | None = None,
|
||||
telemetry: LLMTelemetryContext | None = None,
|
||||
request_metadata: dict[str, str] | None = None,
|
||||
) -> HonchoLLMCallResponse[str]: ...
|
||||
|
||||
|
||||
|
|
@ -135,6 +137,7 @@ async def honcho_llm_call(
|
|||
trace_name: str | None = None,
|
||||
iteration_callback: IterationCallback | None = None,
|
||||
telemetry: LLMTelemetryContext | None = None,
|
||||
request_metadata: dict[str, str] | None = None,
|
||||
) -> AsyncIterator[HonchoLLMCallStreamChunk] | StreamingResponseWithMetadata: ...
|
||||
|
||||
|
||||
|
|
@ -165,6 +168,7 @@ async def honcho_llm_call(
|
|||
trace_name: str | None = None,
|
||||
iteration_callback: IterationCallback | None = None,
|
||||
telemetry: LLMTelemetryContext | None = None,
|
||||
request_metadata: dict[str, str] | None = None,
|
||||
) -> (
|
||||
HonchoLLMCallResponse[Any]
|
||||
| AsyncIterator[HonchoLLMCallStreamChunk]
|
||||
|
|
@ -243,6 +247,7 @@ async def honcho_llm_call(
|
|||
selected_config=plan.selected_config,
|
||||
plan=plan,
|
||||
telemetry=telemetry,
|
||||
request_metadata=request_metadata,
|
||||
)
|
||||
return await honcho_llm_call_inner(
|
||||
plan.provider,
|
||||
|
|
@ -263,6 +268,7 @@ async def honcho_llm_call(
|
|||
selected_config=plan.selected_config,
|
||||
plan=plan,
|
||||
telemetry=telemetry,
|
||||
request_metadata=request_metadata,
|
||||
)
|
||||
|
||||
decorated = _call_with_provider_selection
|
||||
|
|
@ -373,6 +379,7 @@ async def honcho_llm_call(
|
|||
plan=plan,
|
||||
telemetry=telemetry,
|
||||
messages=captured_messages,
|
||||
request_metadata=request_metadata,
|
||||
)
|
||||
return await honcho_llm_call_inner(
|
||||
plan.provider,
|
||||
|
|
@ -394,6 +401,7 @@ async def honcho_llm_call(
|
|||
plan=plan,
|
||||
telemetry=telemetry,
|
||||
messages=captured_messages,
|
||||
request_metadata=request_metadata,
|
||||
)
|
||||
|
||||
wrapped = _toolless_call
|
||||
|
|
|
|||
|
|
@ -322,6 +322,8 @@ class OpenAIBackend:
|
|||
):
|
||||
if key in extra_params:
|
||||
params[key] = extra_params[key]
|
||||
if "metadata" in extra_params:
|
||||
params["metadata"] = extra_params["metadata"]
|
||||
return params
|
||||
|
||||
def _normalize_response(
|
||||
|
|
|
|||
|
|
@ -210,6 +210,7 @@ async def honcho_llm_call_inner(
|
|||
selected_config: ModelConfig | None = None,
|
||||
plan: AttemptPlan | None = None,
|
||||
telemetry: LLMTelemetryContext | None = None,
|
||||
request_metadata: dict[str, str] | None = None,
|
||||
) -> HonchoLLMCallResponse[M]: ...
|
||||
|
||||
|
||||
|
|
@ -234,6 +235,7 @@ async def honcho_llm_call_inner(
|
|||
selected_config: ModelConfig | None = None,
|
||||
plan: AttemptPlan | None = None,
|
||||
telemetry: LLMTelemetryContext | None = None,
|
||||
request_metadata: dict[str, str] | None = None,
|
||||
) -> HonchoLLMCallResponse[str]: ...
|
||||
|
||||
|
||||
|
|
@ -258,6 +260,7 @@ async def honcho_llm_call_inner(
|
|||
selected_config: ModelConfig | None = None,
|
||||
plan: AttemptPlan | None = None,
|
||||
telemetry: LLMTelemetryContext | None = None,
|
||||
request_metadata: dict[str, str] | None = None,
|
||||
) -> AsyncIterator[HonchoLLMCallStreamChunk]: ...
|
||||
|
||||
|
||||
|
|
@ -281,6 +284,7 @@ async def honcho_llm_call_inner(
|
|||
selected_config: ModelConfig | None = None,
|
||||
plan: AttemptPlan | None = None,
|
||||
telemetry: LLMTelemetryContext | None = None,
|
||||
request_metadata: dict[str, str] | None = None,
|
||||
) -> HonchoLLMCallResponse[Any] | AsyncIterator[HonchoLLMCallStreamChunk]:
|
||||
"""One backend call. No retry, no fallback, no tool loop.
|
||||
|
||||
|
|
@ -318,6 +322,8 @@ async def honcho_llm_call_inner(
|
|||
# knobs — they pass through extra_params. execute_completion merges
|
||||
# build_config_extra_params(effective_config) on top for top_p/seed/etc.
|
||||
call_extras: dict[str, Any] = {"json_mode": json_mode, "verbosity": verbosity}
|
||||
if request_metadata is not None:
|
||||
call_extras["metadata"] = request_metadata
|
||||
|
||||
if stream:
|
||||
# Stream path: setup must run inside the awaited coroutine so it
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ class TestDeriverProcessing:
|
|||
== expected_config.thinking_budget_tokens
|
||||
)
|
||||
assert kwargs["model_config"].stop_sequences == expected_config.stop_sequences
|
||||
assert kwargs["request_metadata"] == {"namespace": settings.NAMESPACE}
|
||||
assert "llm_settings" not in kwargs
|
||||
|
||||
async def test_process_representation_tasks_batch_passes_custom_instructions_into_prompt(
|
||||
|
|
|
|||
|
|
@ -227,6 +227,44 @@ async def test_openai_backend_skips_extra_body_when_thinking_budget_zero() -> No
|
|||
assert "extra_body" not in call
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_openai_backend_passes_request_metadata() -> None:
|
||||
client = Mock()
|
||||
client.chat.completions.create = AsyncMock(
|
||||
return_value=SimpleNamespace(
|
||||
choices=[
|
||||
SimpleNamespace(
|
||||
finish_reason="stop",
|
||||
message=SimpleNamespace(
|
||||
content="ok",
|
||||
tool_calls=[],
|
||||
reasoning_details=[],
|
||||
),
|
||||
)
|
||||
],
|
||||
usage=SimpleNamespace(
|
||||
prompt_tokens=10,
|
||||
completion_tokens=5,
|
||||
prompt_tokens_details=None,
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
backend = OpenAIBackend(client)
|
||||
await backend.complete(
|
||||
model="gpt-4.1",
|
||||
messages=[{"role": "user", "content": "Hello"}],
|
||||
max_tokens=100,
|
||||
extra_params={"metadata": {"namespace": "honcho"}},
|
||||
)
|
||||
|
||||
await_args = client.chat.completions.create.await_args
|
||||
if await_args is None:
|
||||
raise AssertionError("Expected OpenAI create call")
|
||||
call = await_args.kwargs
|
||||
assert call["metadata"] == {"namespace": "honcho"}
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_openai_backend_converts_anthropic_style_tools() -> None:
|
||||
client = Mock()
|
||||
|
|
|
|||
Loading…
Reference in New Issue