Entropic 2.11.1
Local-first agentic inference engine
Loading...
Searching...
No Matches
response_parse.h File Reference

One template-first / adapter-second parse rule for raw model output. More...

#include <entropic/inference/adapters/adapter_base.h>
#include <entropic/types/tool_call.h>
#include <string>
#include <vector>
Include dependency graph for response_parse.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  entropic::ParsedModelResponse
 Content and tool calls extracted from one raw emission. More...
 

Namespaces

namespace  entropic
 Activate model on GPU (WARM → ACTIVE).
 

Functions

bool entropic::calls_satisfy_schema (const std::vector< ToolCall > &calls, const std::string &tools_json)
 Check that every call's declared required parameters are present.
 
ParsedModelResponse entropic::parse_model_response (LlamaCppBackend *llama, ChatAdapter *adapter, const std::string &raw)
 Parse a raw emission: template first, adapter second.
 

Detailed Description

One template-first / adapter-second parse rule for raw model output.

Why this exists (gh#108, v2.10.3)
The same branch was written twice — orchestrator.cpp (buffered generate result) and interface_factory.cpp (agent-loop tool parse) — each choosing between llama.cpp's common_chat parser and the engine's ChatAdapter. The duplication is how a fix reached one path and not the other.

It also encoded the wrong relationship. common_chat_parse_reliable() is parse_params_valid_ && format == PEG_GEMMA4: it exists to say *"this captured format is multi-parameter safe"*, and thinking-block removal got bolted onto it. So reasoning stripping only happened for gemma4, and only when a TOOLED render had captured a parser arena — a toolless generate fell to the adapter branch with no channel handling at all.

The rule here separates the two concerns, because they compose differently:

  • Content cleanup composes. Run the template parse when an arena exists, then ALWAYS run the adapter's strip over the result. Stripping is idempotent — if the template already removed reasoning, the second pass is a no-op — so no decision logic is needed and no path can be missed.
  • Tool-call extraction does not compose. Two call lists cannot be merged safely, so it is genuinely either/or. The template wins when its result is trustworthy; the adapter is the fallback.
Why the tool-call fallback needs an a-posteriori check
common_chat's PEG autoparser extracts only the FIRST <parameter=> of a multi-parameter call (gh#87 Phase D) — and it does so silently, returning a well-formed ToolCall with arguments missing. A try/catch fallback would never fire. So the template result is validated against the staged tool schema, and a call missing declared required parameters routes to the adapter's hand-rolled parser (xml_parameter_parser, which also tolerates the gh#79 </NAME> close tag). Without this, moving Qwen/Nemotron onto the template path would quietly drop arguments.
Version
2.10.3

Definition in file response_parse.h.