Prompt Tools 0.3.2
Loading...
Searching...
No Matches
openai_provider.hpp
Go to the documentation of this file.
1#pragma once
2
4
5namespace prompt
6{
7
17{
18public:
26
34 virtual void initialize(rclcpp::Node::SharedPtr node) override
35 {
36 // initialize base class
37 initialize_prompt_base(node, "OpenAIProvider", "OPENAI_API_KEY");
38 }
39
40protected:
50 virtual Poco::JSON::Object toJson(prompt::PromptRequest& prompt) override
51 {
52 // add options (model, temperature, etc.)
53 Poco::JSON::Object result = handle_options(prompt.options);
54
55 // /v1/responses uses `input` instead of `prompt`
56 // For simple one-shot prompts, send the text directly as a string.
57 result.set("input", prompt.prompt);
58
59 return result;
60 }
61
72 virtual Poco::JSON::Object toJsonConversation(prompt::PromptRequest& prompt,
73 std::vector<PromptDialogue>& conversation) override
74 {
75 // add options (model, temperature, etc.)
76 Poco::JSON::Object result = handle_options(prompt.options);
77
78 // /v1/responses represents conversational input as an array of "message" items
79 // Each message has: role + content array with input_text/output_text entries.
80 Poco::JSON::Array input_array;
81
82 // add previous conversation
83 for (const prompt::PromptDialogue& dialog : conversation)
84 {
85 Poco::JSON::Object message_obj;
86 message_obj.set("type", "message");
87 message_obj.set("role", dialog.role);
88
89 Poco::JSON::Array content_array;
90 Poco::JSON::Object content_obj;
91 content_obj.set("type", "input_text");
92 content_obj.set("text", dialog.content);
93 content_array.add(content_obj);
94
95 message_obj.set("content", content_array);
96 input_array.add(message_obj);
97 }
98
99 // add latest user prompt as the final message
100 Poco::JSON::Object latest_message;
101 latest_message.set("type", "message");
102 latest_message.set("role", "user");
103
104 Poco::JSON::Array latest_content_array;
105 Poco::JSON::Object latest_content_obj;
106 latest_content_obj.set("type", "input_text");
107 latest_content_obj.set("text", prompt.prompt);
108 latest_content_array.add(latest_content_obj);
109
110 latest_message.set("content", latest_content_array);
111 input_array.add(latest_message);
112
113 // attach to body as `input`
114 result.set("input", input_array);
115
116 return result;
117 }
118
128 virtual prompt::PromptResponse fromJson(const Poco::JSON::Object::Ptr object) override
129 {
131
132 // Extract assistant text from /v1/responses `output` structure
133 if (object->has("output"))
134 {
135 try
136 {
137 Poco::JSON::Array::Ptr output_array = object->getArray("output");
138 for (size_t i = 0; i < output_array->size(); ++i)
139 {
140 Poco::JSON::Object::Ptr out_item = output_array->getObject(i);
141 if (!out_item->has("content"))
142 continue;
143
144 Poco::JSON::Array::Ptr content_array = out_item->getArray("content");
145 for (size_t j = 0; j < content_array->size(); ++j)
146 {
147 Poco::JSON::Object::Ptr content_obj = content_array->getObject(j);
148 if (content_obj->has("text"))
149 {
150 res.response = content_obj->getValue<std::string>("text");
151 break;
152 }
153 }
154
155 if (!res.response.empty())
156 break;
157 }
158 }
159 catch (const Poco::Exception& ex)
160 {
161 RCLCPP_WARN(node_->get_logger(), "Failed to parse OpenAI /v1/responses output: %s", ex.what());
162 }
163 }
164
165 res.success = !res.response.empty();
166
167 // attach remaining top-level fields as options (excluding large nested structures)
168 for (Poco::JSON::Object::ConstIterator it = object->begin(); it != object->end(); ++it)
169 {
170 if ((it->first == "output") || (it->first == "usage"))
171 continue;
172
173 try
174 {
175 if (!it->second.isEmpty() && it->second.isString())
176 {
177 res.options.push_back(prompt::PromptOption{ it->first, it->second.convert<std::string>(), "" });
178 }
179 else if (!it->second.isEmpty())
180 {
181 res.options.push_back(prompt::PromptOption{ it->first, it->second.toString(), "" });
182 }
183 else
184 {
185 res.options.push_back(prompt::PromptOption{ it->first, "[null]", "" });
186 }
187 }
188 catch (const Poco::Exception& ex)
189 {
190 RCLCPP_WARN(node_->get_logger(), "Failed to convert JSON key '%s': %s", it->first.c_str(), ex.what());
191 }
192 }
193
194 return res;
195 }
196
207 virtual prompt::PromptResponse fromJsonConversation(const Poco::JSON::Object::Ptr object) override
208 {
210 // Parse the same /v1/responses structure for conversational responses
211 if (object->has("output"))
212 {
213 try
214 {
215 Poco::JSON::Array::Ptr output_array = object->getArray("output");
216 for (size_t i = 0; i < output_array->size(); ++i)
217 {
218 Poco::JSON::Object::Ptr out_item = output_array->getObject(i);
219 if (!out_item->has("content"))
220 continue;
221
222 Poco::JSON::Array::Ptr content_array = out_item->getArray("content");
223 for (size_t j = 0; j < content_array->size(); ++j)
224 {
225 Poco::JSON::Object::Ptr content_obj = content_array->getObject(j);
226 if (content_obj->has("text"))
227 {
228 res.response = content_obj->getValue<std::string>("text");
229 break;
230 }
231 }
232
233 if (!res.response.empty())
234 break;
235 }
236 }
237 catch (const Poco::Exception& ex)
238 {
239 RCLCPP_WARN(node_->get_logger(), "Failed to parse OpenAI /v1/responses output (conversation): %s", ex.what());
240 }
241 }
242
243 res.success = !res.response.empty();
244
245 // Attach remaining top-level fields as options (excluding large nested structures)
246 for (Poco::JSON::Object::ConstIterator it = object->begin(); it != object->end(); ++it)
247 {
248 if ((it->first == "output") || (it->first == "usage"))
249 continue;
250
251 try
252 {
253 if (!it->second.isEmpty() && it->second.isString())
254 {
255 res.options.push_back(prompt::PromptOption{ it->first, it->second.convert<std::string>(), "" });
256 }
257 else if (!it->second.isEmpty())
258 {
259 res.options.push_back(prompt::PromptOption{ it->first, it->second.toString(), "" });
260 }
261 else
262 {
263 res.options.push_back(prompt::PromptOption{ it->first, "[null]", "" });
264 }
265 }
266 catch (const Poco::Exception& ex)
267 {
268 RCLCPP_WARN(node_->get_logger(), "Failed to convert JSON key '%s': %s", it->first.c_str(), ex.what());
269 }
270 }
271
272 // Clean up any fenced XML blocks if present (for backward compatibility)
273 size_t startPos = res.response.find("```xml\n");
274 if (startPos != std::string::npos)
275 {
276 res.response.replace(startPos, 6, "");
277 }
278
279 size_t endPos = res.response.rfind("\n```");
280 if (endPos != std::string::npos)
281 {
282 res.response.replace(endPos, 4, "");
283 }
284
285 return res;
286 }
287};
288
289} // namespace prompt
rclcpp::Node::SharedPtr node_
Node shared pointer.
Definition base_class.hpp:105
OpenAIProvider.
Definition openai_provider.hpp:17
OpenAIProvider()
Construct a new Chat Prompt Provider OpenAI object.
Definition openai_provider.hpp:23
virtual void initialize(rclcpp::Node::SharedPtr node) override
Initialize the OpenAIProvider.
Definition openai_provider.hpp:34
virtual Poco::JSON::Object toJson(prompt::PromptRequest &prompt) override
Convert a prompt request to a JSON object.
Definition openai_provider.hpp:50
virtual Poco::JSON::Object toJsonConversation(prompt::PromptRequest &prompt, std::vector< PromptDialogue > &conversation) override
Convert a prompt request with conversation history to a JSON object.
Definition openai_provider.hpp:72
virtual prompt::PromptResponse fromJson(const Poco::JSON::Object::Ptr object) override
Convert a JSON object to a prompt response.
Definition openai_provider.hpp:128
virtual prompt::PromptResponse fromJsonConversation(const Poco::JSON::Object::Ptr object) override
Convert a JSON object to a prompt response with conversation history.
Definition openai_provider.hpp:207
PromptBaseClass.
Definition prompt_base_class.hpp:17
virtual void initialize_prompt_base(rclcpp::Node::SharedPtr node, std::string plugin_name="PromptBaseClass", std::string api_key_name="")
Initialize the REST base class.
Definition prompt_base_class.hpp:45
virtual const Poco::JSON::Object handle_options(std::vector< prompt::PromptOption > &options)
Process options from the prompt request.
Definition rest_base_class.hpp:314
Definition base_class.hpp:8
Definition structs.hpp:17
Definition structs.hpp:9
Definition structs.hpp:24
Definition structs.hpp:35
bool success
Definition structs.hpp:39
std::string response
Definition structs.hpp:36
std::vector< PromptOption > options
Definition structs.hpp:38