MCPcopy Create free account
hub / github.com/AI45Lab/Code / generate_blocking

Function generate_blocking

core/src/llm/structured.rs:112–181  ·  view source on GitHub ↗

Generate a structured JSON object using the given LLM client. Selects the best mode based on `req.mode`, calls the LLM, validates against the schema, and retries with repair prompts if validation fails.

(
    client: &dyn LlmClient,
    req: &StructuredRequest,
)

Source from the content-addressed store, hash-verified

110/// Selects the best mode based on `req.mode`, calls the LLM, validates against
111/// the schema, and retries with repair prompts if validation fails.
112pub async fn generate_blocking(
113 client: &dyn LlmClient,
114 req: &StructuredRequest,
115) -> Result<StructuredResult> {
116 let mode = resolve_mode(req.mode, client.native_structured_support());
117 let mut messages = build_initial_messages(req, mode);
118 let system = build_system_prompt(req, mode);
119 let tools = build_tools(req, mode);
120 let directive = build_directive(req, mode);
121
122 let mut total_usage = TokenUsage::default();
123 let mut repair_rounds: u8 = 0;
124
125 loop {
126 let resp = client
127 .complete_structured(&messages, Some(&system), &tools, &directive)
128 .await
129 .context("LLM call failed during structured generation")?;
130
131 accumulate_usage(&mut total_usage, &resp.usage);
132
133 // Mine the object from every place a model might have parked it (tool call,
134 // text content, AND the reasoning channel), trying each balanced JSON
135 // candidate against the schema. Reasoning models routinely leave `content`
136 // empty and emit the object inside `reasoning`, so without the reasoning
137 // fallback generate_object failed with "no structured output" across models.
138 let candidates = extract_raw_candidates(&resp.message, mode);
139 let resolution = resolve_structured(&candidates, &req.schema);
140
141 if let Some((value, raw)) = resolution.valid {
142 return Ok(StructuredResult {
143 object: value,
144 raw_text: Some(raw),
145 usage: total_usage,
146 repair_rounds,
147 mode_used: mode,
148 });
149 }
150
151 if repair_rounds >= req.max_repair_attempts {
152 return Err(match resolution.invalid {
153 Some((_, errors)) => anyhow::anyhow!(
154 "Structured output failed schema validation after {} repair attempts. Errors: {}",
155 repair_rounds,
156 errors.join("; ")
157 ),
158 None => anyhow::anyhow!(
159 "Structured output parsing failed after {} repair attempts: no JSON object found in tool call, text content, or reasoning channel",
160 repair_rounds
161 ),
162 });
163 }
164
165 repair_rounds += 1;
166 let (repair_msg, raw_for_ctx) = match resolution.invalid {
167 Some((raw, errors)) => (build_repair_message(&raw, &errors), raw),
168 None => {
169 let raw = resolution.raw_seen.unwrap_or_default();

Calls 14

resolve_modeFunction · 0.85
build_initial_messagesFunction · 0.85
build_system_promptFunction · 0.85
build_toolsFunction · 0.85
build_directiveFunction · 0.85
accumulate_usageFunction · 0.85
extract_raw_candidatesFunction · 0.85
resolve_structuredFunction · 0.85
build_repair_messageFunction · 0.85
append_repair_contextFunction · 0.85
contextMethod · 0.80