77inline void to_json(json& j,
const ToolCall& tc) {
78 j = json{{
"id", tc.
id}, {
"name", tc.
name}, {
"arguments", tc.
arguments}};
84inline void from_json(
const json& j,
ToolCall& tc) {
85 tc.
id = j.value(
"id",
"");
86 tc.
name = j.value(
"name",
"");
97 j[
"tool_calls"] = json::array();
101 j[
"tool_calls"].push_back(tc_j);
113 msg.
role = j.value(
"role",
"");
114 msg.
content = j.value(
"content",
"");
115 if (j.contains(
"tool_calls") && j[
"tool_calls"].is_array()) {
116 for (
const auto& tc_j : j[
"tool_calls"]) {
123 msg.
tool_name = j.value(
"tool_name",
"");
124 if (j.contains(
"image_urls") && j[
"image_urls"].is_array()) {
125 msg.
image_urls = j[
"image_urls"].get<std::vector<std::string>>();
141 json arr = json::array();
142 for (
const auto& msg : messages) {
144 j[
"role"] = msg.role;
146 if (msg.role ==
"tool") {
147 j[
"content"] = msg.content;
148 j[
"tool_call_id"] = msg.tool_call_id;
149 }
else if (!msg.tool_calls.empty()) {
150 j[
"content"] = msg.content.empty() ? json(
nullptr) : json(msg.content);
151 json tc_arr = json::array();
152 for (
const auto& tc : msg.tool_calls) {
155 {
"type",
"function"},
156 {
"function", {{
"name", tc.name}, {
"arguments", tc.arguments}}}
159 j[
"tool_calls"] = tc_arr;
160 }
else if (!msg.image_urls.empty()) {
162 json parts = json::array();
163 if (!msg.content.empty()) {
164 parts.push_back({{
"type",
"text"}, {
"text", msg.content}});
166 for (
auto& url : msg.image_urls) {
167 parts.push_back({{
"type",
"image_url"}, {
"image_url", {{
"url", url}}}});
169 j[
"content"] = parts;
171 j[
"content"] = msg.content;
186 json arr = json::array();
187 for (
const auto& tool : tools) {
189 {
"type",
"function"},
192 {
"description", tool.description},
193 {
"parameters", tool.parameters}
212 auto m = choice.at(
"message");
213 msg.
role = m.value(
"role",
"assistant");
214 msg.
content = (m.contains(
"content") && !m[
"content"].is_null())
215 ? m[
"content"].get<std::string>() :
"";
217 if (m.contains(
"tool_calls") && m[
"tool_calls"].is_array()) {
218 for (
const auto& tc : m[
"tool_calls"]) {
220 call.
id = tc.value(
"id",
"");
221 auto fn = tc.at(
"function");
222 call.
name = fn.value(
"name",
"");
223 call.
arguments = fn.value(
"arguments",
"");
Thin C++ RAII wrapper around yyjson with nlohmann-compatible API.
Token usage statistics for the completion.
int completion_tokens
Number of tokens in the completion.
int prompt_tokens
Number of tokens in the prompt.
int total_tokens
Total tokens used (prompt + completion).
LLM completion response including the message and token usage.
ChatMessage message
The response message from the LLM.
A message in the conversation history.
std::string tool_call_id
ID of the tool call being responded to (role == "tool").
std::string tool_name
Name of the tool being called.
std::string content
Text content of the message.
std::vector< std::string > image_urls
Base64 data URLs or HTTP URLs for vision support.
std::string role
Message role: "user", "assistant", "tool", or "system".
std::vector< ToolCall > tool_calls
Tool calls made by the assistant (if any).
json tools_to_json(const std::vector< ChatTool > &tools)
Convert a vector of ChatTools to OpenAI-compatible JSON format.
json messages_to_json(const std::vector< ChatMessage > &messages)
Convert a vector of ChatMessages to OpenAI-compatible JSON format.
ChatMessage parse_response_message(const json &choice)
Parse an OpenAI API response choice into a ChatMessage.