| 7 | namespace openai { |
| 8 | |
| 9 | nlohmann::json OpenAIRequestBuilder::build_request_json( |
| 10 | const GenerateOptions& options) { |
| 11 | nlohmann::json request{{"model", options.model}, |
| 12 | {"messages", nlohmann::json::array()}}; |
| 13 | |
| 14 | if (options.response_format) { |
| 15 | request["response_format"] = options.response_format.value(); |
| 16 | } |
| 17 | // Build messages array |
| 18 | if (!options.messages.empty()) { |
| 19 | // Prepend system as a message when caller supplies a messages array; the |
| 20 | // OpenAI Chat Completions API takes the system prompt as a leading |
| 21 | // role=system message rather than a separate top-level field. |
| 22 | if (!options.system.empty()) { |
| 23 | request["messages"].push_back( |
| 24 | {{"role", "system"}, {"content", options.system}}); |
| 25 | } |
| 26 | // Use provided messages |
| 27 | for (const auto& msg : options.messages) { |
| 28 | nlohmann::json message; |
| 29 | |
| 30 | // Handle different content types |
| 31 | if (msg.has_tool_results()) { |
| 32 | // OpenAI expects each tool result as a separate message with role |
| 33 | // "tool" |
| 34 | for (const auto& result : msg.get_tool_results()) { |
| 35 | nlohmann::json tool_message; |
| 36 | tool_message["role"] = "tool"; |
| 37 | tool_message["tool_call_id"] = result.tool_call_id; |
| 38 | |
| 39 | if (!result.is_error) { |
| 40 | tool_message["content"] = result.result.dump(); |
| 41 | } else { |
| 42 | tool_message["content"] = "Error: " + result.result.dump(); |
| 43 | } |
| 44 | |
| 45 | request["messages"].push_back(tool_message); |
| 46 | } |
| 47 | continue; // Skip adding the main message |
| 48 | } |
| 49 | |
| 50 | // Handle messages with text and/or tool calls |
| 51 | message["role"] = utils::message_role_to_string(msg.role); |
| 52 | |
| 53 | // Get text content (accumulate all text parts) |
| 54 | std::string text_content = msg.get_text(); |
| 55 | |
| 56 | // Get tool calls |
| 57 | auto tool_calls = msg.get_tool_calls(); |
| 58 | |
| 59 | // Set content - OpenAI expects both text and tool calls in the same |
| 60 | // message |
| 61 | if (!text_content.empty()) { |
| 62 | message["content"] = text_content; |
| 63 | } |
| 64 | |
| 65 | if (!tool_calls.empty()) { |
| 66 | nlohmann::json tool_calls_array = nlohmann::json::array(); |
no test coverage detected