liblloyal 1.0.0
Branched Inference for llama.cpp
Loading...
Searching...
No Matches
chat_out.hpp
Go to the documentation of this file.
1#pragma once
2
3// SPDX-License-Identifier: LicenseRef-FSL-1.1-Apache-2.0
4// Copyright 2026 Lloyal Labs
5
6
28#include "common.hpp"
29#include <llama/llama.h>
30#include <chat.h>
31#include <peg-parser.h>
32#include <exception>
33#include <string>
34#include <vector>
35
44
48struct ToolCall {
49 std::string name;
50 std::string arguments;
51 std::string id;
52};
53
79 std::string content;
80 std::string reasoning_content;
81 std::vector<ToolCall> tool_calls;
82};
83
90ParseResult parse(const std::string& output, common_chat_format format,
91 common_reasoning_format reasoning_format, bool is_partial = false,
92 const std::string& generation_prompt = "",
93 const std::string& parser_data = "") = delete;
94
156 const std::string& output,
157 common_chat_format format,
158 bool is_partial = false,
159 const std::string& generation_prompt = "",
160 const common_peg_arena& parser = {}
161) {
162 ParseResult result;
163
164 try {
165 // Build parser params
166 common_chat_parser_params syntax;
167 syntax.format = format;
168 syntax.generation_prompt = common_chat_input(generation_prompt);
169 syntax.parser = parser;
170
171 // Call llama.cpp's output parser
172 common_chat_msg msg = common_chat_parse(common_chat_input(output), is_partial, syntax);
173
174 // Convert to ParseResult
175 result.content = msg.content;
176 result.reasoning_content = msg.reasoning_content;
177
178 for (const auto& tc : msg.tool_calls) {
179 result.tool_calls.push_back({tc.name, tc.arguments, tc.id});
180 }
181
182 } catch (const std::exception& e) {
183 LLOYAL_LOG_DEBUG("[chat_out::parse] Parse failed: %s, returning raw output", e.what());
184 result.content = output;
185 }
186
187 return result;
188}
189
208 const llama_model* model,
209 const std::string& output,
210 bool is_partial = false
211) {
212 ParseResult result;
213
214 try {
215 // Init templates to detect format
216 common_chat_templates_ptr tmpls = common_chat_templates_init(model, "");
217 if (!tmpls) {
218 result.content = output;
219 return result;
220 }
221
222 // Apply with empty messages to get format detection
223 common_chat_templates_inputs inputs;
224 inputs.messages = {{.role = "user", .content = ""}};
225 inputs.add_generation_prompt = true;
226 inputs.use_jinja = true;
227
228 common_chat_params params = common_chat_templates_apply(tmpls.get(), inputs);
229
230 // Delegate to explicit-format overload
231 return parse(output, params.format, is_partial, params.generation_prompt, params.parser);
232
233 } catch (const std::exception& e) {
234 LLOYAL_LOG_DEBUG("[chat_out::parse] Auto-detect failed: %s", e.what());
235 result.content = output;
236 return result;
237 }
238}
239
240} // namespace lloyal::chat_out
#define LLOYAL_LOG_DEBUG(...)
liblloyal - Common definitions and logging
Definition common.hpp:48
Chat output parsing (tool calls, reasoning, content)
Definition chat_out.hpp:43
ParseResult parse(const std::string &output, common_chat_format format, common_reasoning_format reasoning_format, bool is_partial=false, const std::string &generation_prompt="", const std::string &parser_data="")=delete
The shape before the engine pin moved took a reasoning format third.
std::string generation_prompt
Generation prompt prefill (e.g. "<think>")
Definition chat_in.hpp:95
Result from parsing model output.
Definition chat_out.hpp:78
std::vector< ToolCall > tool_calls
Extracted tool calls (empty array if none)
Definition chat_out.hpp:81
std::string content
Main response text (visible to user)
Definition chat_out.hpp:79
std::string reasoning_content
Extracted thinking/reasoning blocks (empty if none)
Definition chat_out.hpp:80
A single tool call extracted from model output.
Definition chat_out.hpp:48
std::string name
Tool/function name.
Definition chat_out.hpp:49
std::string id
Tool call ID (may be empty if model doesn't generate IDs)
Definition chat_out.hpp:51
std::string arguments
JSON string of arguments.
Definition chat_out.hpp:50