corrections

package
v1.9.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 2, 2026 License: Apache-2.0 Imports: 6 Imported by: 0

Documentation

Overview

Package corrections is Harbor's provider correction layer ( — RFC §6.5). It sits BETWEEN the runtime and the `llm.LLMClient` driver, rewriting `CompleteRequest`s per a per-model `CorrectionsProfile` before delegating, and optionally backfilling `CompleteResponse.Usage` from the request's byte length.

Compose order is settled:

Open() → corrections.Wrap(safety.New(driver))

— the corrections wrapper is the OUTERMOST layer so the safety pass sees the POST-correction request (the final outgoing payload reaching the driver). Materialization, leak-detection, and the token-budget guard all run against the corrected payload, so any future correction that grows token count is caught by the safety pass.

Five quirks:

  1. Message reordering — NIM and some OpenAI-compatible proxies reject mid-thread `system` messages. `OrderingSystemFirstStrict` collapses all system messages to the front.
  2. Schema sanitization — OpenAI's structured-output mode requires `additionalProperties:false`+`strict:true` at every nested object schema; other providers reject those keys. `SchemaSanitizationMode` flips between adding / stripping them.
  3. Reasoning-effort routing — thinking-class models (`o1`, `o3`, `deepseek-reasoner`) consume the effort hint via a provider-specific path. `ReasoningRouteThinking` moves the hint from the top-level field into `req.Extra["reasoning_effort"]`.
  4. Response-format envelope translation — `ResponseFormatJSONOnly` downgrades `FormatJSONSchema` to `FormatJSONObject` for providers that reject `json_schema`; `ResponseFormatAnthropic` packages the schema into Anthropic's tool-schema envelope inside `req.Extra`.
  5. Usage backfill — some streaming proxies report `0/0` tokens. `UsageBackfillEnabled` substitutes an estimate computed from request input length + response content length when the driver returns an all-zeros `Usage`.

Scope is structured-output and message-shape correctness only — NEVER provider-native tool dispatch (RFC §6.4). The smoke static guard extends to this package; the banned provider-native tool-call API symbols MUST NOT appear here. The runtime owns tool dispatch entirely.

Concurrent-reuse: the wrapper is stateless across calls. `Wrap` returns a value that holds an inner `LLMClient` and a `ConfigSnapshot`; both are read-only after construction. The per- call work allocates fresh slices/maps so concurrent callers never share mutable state. The package's `corrections_test.go` pins this with N=128 invocations under `-race`.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DefaultOutputModeFor

func DefaultOutputModeFor(model string) llm.OutputMode

DefaultOutputModeFor returns the per-known-provider default `OutputMode` for the supplied model name. Harbor reads this when the operator's profile leaves `OutputMode` unset.

Defaults:

  • `openai/*` (non-reasoning) → Native (OpenAI supports native json_schema).
  • `openai/o1*`, `openai/o3*`, `*deepseek-reasoner*` → Prompted (thinking-class models behave better with prompted JSON).
  • `anthropic/*` → Native (Anthropic supports structured outputs).
  • `google/*` → Native.
  • `nim/*` and any other prefix → Prompted (the conservative fallback that works for OpenAI-compatible endpoints without native schema support).

The result is purely a fallback — `ProfileFor` returns the operator-supplied `OutputMode` when present.

func ProfileFor

func ProfileFor(cfg llm.ConfigSnapshot, model string) llm.CorrectionsProfile

ProfileFor returns the `CorrectionsProfile` for the given model name. The lookup is operator-config-first; when the operator hasn't declared a profile, a per-known-provider default applies based on the model name prefix.

The defaults table is intentionally small and conservative: the per-provider quirks catalogued in the MCP research notes are encoded as defaults so an operator who omits the corrections block still gets sensible behaviour when running against a known model. An operator who overrides the profile in `harbor.yaml` wins.

This function is exported for tests; production code reads `cfg.ModelProfiles[req.Model].Corrections` directly. The function exists to demonstrate the defaults table and let smoke tests prove the wiring works.

func Wrap

func Wrap(inner llm.LLMClient, cfg llm.ConfigSnapshot) llm.LLMClient

Wrap composes the corrections layer on top of `inner`. The returned `llm.LLMClient` rewrites requests per the profile in `cfg.ModelProfiles[req.Model].Corrections` (zero-valued profile = no-op) and optionally backfills `Usage` on the response.

Production callers wire this through `llm.Open()`; tests that need to exercise the wrapper in isolation can call `Wrap` directly.

A nil `inner` panics — composition error caught at boot.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL