Skip to content

Commit 70809d1

Browse files
committed
feat(api): implement API response generation and refactor payload handling
- Added `generate_api_response` function to streamline API response generation using OpenAI format. - Introduced `build_payload` and `build_headers` functions for better organization of request construction. - Replaced hardcoded system prompt with a constant variable for improved maintainability. - Updated main function to utilize the new response generation logic, enhancing code clarity and functionality.
1 parent c67e6d9 commit 70809d1

File tree

1 file changed

+50
-34
lines changed

1 file changed

+50
-34
lines changed

ask2api.py

Lines changed: 50 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@
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

118126
def 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+
205251
def 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

312328
if __name__ == "__main__":

0 commit comments

Comments
 (0)