anasfsd123 commited on
Commit
bae9e5d
·
verified ·
1 Parent(s): e59caf8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +87 -59
app.py CHANGED
@@ -46,82 +46,110 @@ def get_active_llm_provider():
46
 
47
  def get_llm_summary(prompt: str, context: str = "") -> str:
48
  """
49
- Generate an expert summary using the AI/ML API.
50
- Uses AI_ML_API_KEY (reads from Streamlit secrets or env var).
51
- Robustly handles 200/201 responses and different response content shapes.
 
52
  """
53
- full_prompt = f"{context}\n\n{prompt}" if context else prompt
54
 
55
- # Prefer Streamlit secret then env var (keeps same convention used elsewhere)
56
  api_key = get_env_or_secret("AI_ML_API_KEY") or os.getenv("AI_ML_API_KEY")
57
  if not api_key:
58
  return (
59
- "AI Analysis unavailable — AI_ML_API_KEY not configured.\n"
 
60
  "Go to Settings → Secrets → Create secret 'AI_ML_API_KEY' with your AI/ML API key."
61
  )
62
 
63
  url = "https://api.aimlapi.com/v1/responses"
64
- headers = {
65
- "Content-Type": "application/json",
66
- "Authorization": f"Bearer {api_key}"
67
- }
68
- payload = {
 
 
 
 
 
 
 
 
 
69
  "model": "openai/gpt-5-2025-08-07",
70
  "input": full_prompt,
71
- # Optionally tune these: 'max_output_tokens': 512, 'temperature': 0.7
 
 
 
72
  }
73
 
74
- try:
75
- resp = requests.post(url, headers=headers, json=payload, timeout=60)
76
- # AIML API commonly returns 201 on success for /responses
77
- if resp.status_code not in (200, 201):
78
- return f"AI Analysis Error (AIML API {resp.status_code}): {resp.text}"
79
-
80
- data = resp.json()
81
-
82
- # 1) Try the helper top-level output_text if present (docs show this field).
83
- if data.get("output_text"):
84
- return data["output_text"]
85
 
86
- # 2) Otherwise, inspect `output` array for message items with content → output_text
87
- output_items = data.get("output", []) or []
88
  texts = []
89
- for item in output_items:
90
- # item might be 'message' with 'content' list
91
- if item.get("type") == "message" and isinstance(item.get("content"), list):
 
 
 
 
 
 
 
 
 
92
  for c in item["content"]:
93
- if c.get("type") in ("output_text", "text") and c.get("text"):
94
- texts.append(c["text"])
95
- # some items can include 'text' directly (defensive)
96
- elif isinstance(item.get("text"), str) and item.get("text").strip():
97
- texts.append(item.get("text"))
98
-
99
- if texts:
100
- return "\n\n".join(texts)
101
-
102
- # 3) Some models may include 'responses' list in other shapes; attempt fallback
103
- if "responses" in data and isinstance(data["responses"], list) and len(data["responses"]) > 0:
104
- first = data["responses"][0]
105
- # try a few typical fields
106
- for field in ("text", "output_text", "content"):
107
- v = first.get(field)
108
- if isinstance(v, str) and v.strip():
109
- return v
110
- if isinstance(v, list):
111
- # flatten content lists if present
112
- for el in v:
113
- if isinstance(el, dict) and el.get("text"):
114
- texts.append(el["text"])
115
- if texts:
116
- return "\n\n".join(texts)
117
-
118
- # If we reach here, the response had no text content we could extract
119
- return "AI Analysis returned no text output. Raw response excerpt: " + json.dumps(data)[:1200]
 
 
 
 
 
 
 
 
 
 
 
 
120
 
121
- except requests.exceptions.RequestException as e:
122
- return f"AI Analysis Request Failed (network): {e}"
123
- except Exception as e:
124
- return f"AI Analysis Request Failed (parsing): {e}"
 
 
125
 
126
 
127
  # =============================
 
46
 
47
  def get_llm_summary(prompt: str, context: str = "") -> str:
48
  """
49
+ Robust LLM summary using AIML /responses.
50
+ - Requests text response_format and low reasoning effort by default.
51
+ - Parses: output_text, output -> message/content (output_text/text), and reasoning -> summary.
52
+ - If only reasoning is returned, retries once with safer params.
53
  """
54
+ full_prompt = f"{context}
55
 
56
+ {prompt}" if context else prompt
57
  api_key = get_env_or_secret("AI_ML_API_KEY") or os.getenv("AI_ML_API_KEY")
58
  if not api_key:
59
  return (
60
+ "AI Analysis unavailable — AI_ML_API_KEY not configured.
61
+ "
62
  "Go to Settings → Secrets → Create secret 'AI_ML_API_KEY' with your AI/ML API key."
63
  )
64
 
65
  url = "https://api.aimlapi.com/v1/responses"
66
+ headers = {"Content-Type": "application/json", "Authorization": f"Bearer {api_key}"}
67
+
68
+ def call_api(payload):
69
+ try:
70
+ r = requests.post(url, headers=headers, json=payload, timeout=90)
71
+ if r.status_code not in (200, 201):
72
+ return None, f"AI Analysis Error (AIML API {r.status_code}): {r.text}"
73
+ return r.json(), None
74
+ except requests.exceptions.RequestException as e:
75
+ return None, f"AI Analysis Request Failed (network): {e}"
76
+ except Exception as e:
77
+ return None, f"AI Analysis Request Failed (parsing): {e}"
78
+
79
+ base_payload = {
80
  "model": "openai/gpt-5-2025-08-07",
81
  "input": full_prompt,
82
+ "max_output_tokens": 1024,
83
+ "temperature": 0.0,
84
+ "reasoning_effort": "low",
85
+ "response_format": {"type": "text"},
86
  }
87
 
88
+ data, error = call_api(base_payload)
89
+ if error:
90
+ return error
 
 
 
 
 
 
 
 
91
 
92
+ def extract_text_from_response(data_dict):
 
93
  texts = []
94
+
95
+ if data_dict.get("output_text"):
96
+ texts.append(data_dict["output_text"])
97
+
98
+ for item in data_dict.get("output", []) or []:
99
+ itype = item.get("type", "")
100
+ if itype == "reasoning":
101
+ for s in item.get("summary", []) or []:
102
+ t = s.get("text") or s.get("summary") or ""
103
+ if isinstance(t, str) and t.strip():
104
+ texts.append(t.strip())
105
+ if itype == "message" and isinstance(item.get("content"), list):
106
  for c in item["content"]:
107
+ if isinstance(c, dict):
108
+ txt = c.get("text") or c.get("output_text") or ""
109
+ if isinstance(txt, str) and txt.strip():
110
+ texts.append(txt.strip())
111
+ if isinstance(item.get("text"), str) and item.get("text").strip():
112
+ texts.append(item.get("text").strip())
113
+
114
+ if not texts and "responses" in data_dict:
115
+ for r in data_dict["responses"]:
116
+ if isinstance(r, dict):
117
+ for f in ("output_text", "text"):
118
+ v = r.get(f)
119
+ if isinstance(v, str) and v.strip():
120
+ texts.append(v.strip())
121
+ cont = r.get("content")
122
+ if isinstance(cont, list):
123
+ for c in cont:
124
+ if isinstance(c, dict) and c.get("text"):
125
+ texts.append(c["text"].strip())
126
+ return "
127
+
128
+ ".join(texts).strip()
129
+
130
+ out_text = extract_text_from_response(data)
131
+ if out_text:
132
+ return out_text
133
+
134
+ retry_payload = base_payload.copy()
135
+ retry_payload.update({
136
+ "reasoning_effort": "low",
137
+ "temperature": 0.0,
138
+ "max_output_tokens": 2048
139
+ })
140
+ data2, err2 = call_api(retry_payload)
141
+ if err2:
142
+ return err2
143
+ out_text2 = extract_text_from_response(data2)
144
+ if out_text2:
145
+ return out_text2
146
 
147
+ try:
148
+ return "AI Analysis returned no text output. Raw response excerpt: " + json.dumps(data)[:1600]
149
+ except Exception:
150
+ return "AI Analysis returned no text output and response could not be serialized."
151
+
152
+ # =============================
153
 
154
 
155
  # =============================