2323 "object" : "object" ,
2424 "dict" : "object" ,
2525}
26+ SYSTEM_PROMPT = """
27+ You are a JSON API engine.
28+
29+ You must answer every user request as a valid API response that strictly
30+ follows the given JSON schema.
31+
32+ Never return markdown, comments or extra text.
33+ """
2634
2735
2836@dataclass
@@ -47,7 +55,7 @@ class Config:
4755 def __post_init__ (self ):
4856 if not self .api_key :
4957 raise ValueError ("API key is not set!" )
50- self .openai_url = f"{ self .base_url } /chat/completions"
58+ self .url = f"{ self .base_url } /chat/completions"
5159
5260 @classmethod
5361 def get_env_vars_help (cls ):
@@ -116,7 +124,7 @@ def encode_image(image_path):
116124
117125
118126def prepare_image_content (image_path ):
119- """Prepare image content for OpenAI API (either URL or base64 encoded)."""
127+ """Prepare image content (either URL or base64 encoded)."""
120128 if is_url (image_path ):
121129 return {"type" : "image_url" , "image_url" : {"url" : image_path }}
122130 else :
@@ -202,6 +210,44 @@ def read_text_file(path):
202210 return f .read ().strip ()
203211
204212
213+ def build_payload (user_content , schema , config ):
214+ """Build the payload for the OpenAI format."""
215+ return {
216+ "model" : config .model ,
217+ "messages" : [
218+ {"role" : "system" , "content" : SYSTEM_PROMPT },
219+ {"role" : "user" , "content" : user_content },
220+ ],
221+ "response_format" : {
222+ "type" : "json_schema" ,
223+ "json_schema" : {"name" : "ask2api_schema" , "schema" : schema },
224+ },
225+ "temperature" : config .temperature ,
226+ }
227+
228+
229+ def build_headers (config ):
230+ """Build the headers for the OpenAI format."""
231+ return {
232+ "Authorization" : f"Bearer { config .api_key } " ,
233+ "Content-Type" : "application/json" ,
234+ }
235+
236+
237+ def generate_api_response (
238+ user_content : str | list [dict ],
239+ schema : dict ,
240+ config : Config ,
241+ ) -> dict :
242+ """Generate an API response using the OpenAI format."""
243+ headers = build_headers (config )
244+ payload = build_payload (user_content , schema , config )
245+ response = requests .post (config .url , headers = headers , json = payload )
246+ response .raise_for_status ()
247+ content = response .json ()["choices" ][0 ]["message" ]["content" ]
248+ return json .loads (content )
249+
250+
205251def main ():
206252 parser = argparse .ArgumentParser (
207253 formatter_class = argparse .RawDescriptionHelpFormatter ,
@@ -261,15 +307,6 @@ def main():
261307 example = json .loads (example_str )
262308 schema = convert_example_to_schema (example )
263309
264- system_prompt = """
265- You are a JSON API engine.
266-
267- You must answer every user request as a valid API response that strictly
268- follows the given JSON schema.
269-
270- Never return markdown, comments or extra text.
271- """
272-
273310 # Build user message content
274311 if args .image :
275312 # Multimodal content: text + image
@@ -283,30 +320,9 @@ def main():
283320
284321 config = Config .from_env ()
285322
286- payload = {
287- "model" : config .model ,
288- "messages" : [
289- {"role" : "system" , "content" : system_prompt },
290- {"role" : "user" , "content" : user_content },
291- ],
292- "response_format" : {
293- "type" : "json_schema" ,
294- "json_schema" : {"name" : "ask2api_schema" , "schema" : schema },
295- },
296- "temperature" : config .temperature ,
297- }
298-
299- headers = {
300- "Authorization" : f"Bearer { config .api_key } " ,
301- "Content-Type" : "application/json" ,
302- }
303-
304- r = requests .post (config .openai_url , headers = headers , json = payload )
305- r .raise_for_status ()
323+ result = generate_api_response (user_content , schema , config )
306324
307- result = r .json ()["choices" ][0 ]["message" ]["content" ]
308- parsed_result = json .loads (result )
309- print (json .dumps (parsed_result , indent = 2 , ensure_ascii = False ))
325+ print (json .dumps (result , indent = 2 , ensure_ascii = False ))
310326
311327
312328if __name__ == "__main__" :
0 commit comments