saiteja020 commited on
Commit
ebe0bd3
·
1 Parent(s): 6149154
backend/api/__pycache__/llm_evaluator.cpython-313.pyc CHANGED
Binary files a/backend/api/__pycache__/llm_evaluator.cpython-313.pyc and b/backend/api/__pycache__/llm_evaluator.cpython-313.pyc differ
 
backend/api/llm_evaluator.py CHANGED
@@ -1,14 +1,23 @@
1
  """
2
- LLM Evaluator – analyzes BESS-RL evaluation results using Gemini or Hugging Face.
3
  Includes a heuristic fallback for when API quotas are exceeded.
 
4
  """
5
  import os
6
  import json
7
  import requests
 
8
 
9
- GEMINI_MODEL = os.getenv("GEMINI_MODEL", "gemini-1.5-flash")
10
- HF_MODEL = os.getenv("HF_MODEL", "google/gemma-2-9b-it")
11
- LLM_PROVIDER = os.getenv("LLM_PROVIDER", "GEMINI").upper()
 
 
 
 
 
 
 
12
 
13
  _FALLBACK_BASE = {
14
  "available": False,
@@ -25,27 +34,18 @@ _FALLBACK_BASE = {
25
  "provider": "UNKNOWN"
26
  }
27
 
28
- TASK_DESCRIPTIONS = {
29
- "easy": "Energy Arbitrage only (buy cheap, sell expensive)",
30
- "medium": "Energy Arbitrage + Frequency Regulation",
31
- "hard": "Energy Arbitrage + Frequency Regulation + Peak Shaving",
32
- }
33
-
34
  def _get_heuristic_analysis(data: dict) -> dict:
35
  """Provides a rule-based assessment when LLMs are unavailable."""
36
  scores = data.get("scores", {})
37
  overall = scores.get("overall", 0)
38
  task = data.get("task", "hard")
39
 
40
- # Determine Verdict
41
  if overall >= 0.85: verdict = "Excellent"
42
  elif overall >= 0.70: verdict = "Good"
43
  elif overall >= 0.50: verdict = "Needs Improvement"
44
  else: verdict = "Poor"
45
 
46
  strengths, weaknesses, recommendations = [], [], []
47
-
48
- # Analysis logic
49
  if scores.get("reward", 0) > 0.8: strengths.append("Strong reward optimization")
50
  else: weaknesses.append("Sub-optimal profit generation")
51
 
@@ -60,8 +60,6 @@ def _get_heuristic_analysis(data: dict) -> dict:
60
  weaknesses.append("Aggressive battery cycling")
61
  recommendations.append("Increase degradation cost coefficient to preserve battery health")
62
 
63
- # Calculate an independent heuristic score (weighted average of components)
64
- # This makes the heuristic score distinct from the simulator's engine score
65
  h_score = (
66
  scores.get("reward", 0) * 0.4 +
67
  scores.get("soc_readiness", 0) * 0.2 +
@@ -126,101 +124,56 @@ Cycle Discipline : {scores.get('cycle_discipline', 0):.3f}
126
  }}
127
  """
128
 
129
- def _get_gemini_analysis(data: dict) -> dict:
130
- api_key = os.getenv("GEMINI_API_KEY") or os.getenv("GEMINI_TOKEN")
131
- if not api_key: raise ValueError("GEMINI_API_KEY not found in Space secrets.")
 
 
132
 
133
- from google import genai
134
- from google.genai import types
135
- client = genai.Client(api_key=api_key)
136
- prompt = _build_prompt(data)
137
- response = client.models.generate_content(
138
- model=GEMINI_MODEL,
139
- contents=prompt,
140
- config=types.GenerateContentConfig(
141
- temperature=0.3,
142
- ),
143
  )
144
- # Extract JSON string safely
145
- text = response.text.strip()
146
- if "```json" in text:
147
- text = text.split("```json")[1].split("```")[0]
148
- elif "```" in text:
149
- text = text.split("```")[1].split("```")[0]
150
-
151
- return {**json.loads(text.strip()), "available": True, "provider": "GEMINI"}
152
-
153
- def _get_openai_analysis(data: dict, model_name: str) -> dict:
154
- api_key = os.getenv("OPENAI_API_KEY") or os.getenv("OPENAI_TOKEN")
155
- if not api_key: raise ValueError("OPENAI_API_KEY not found in Space secrets.")
156
 
157
- import openai
158
- client = openai.OpenAI(api_key=api_key)
159
  prompt = _build_prompt(data)
160
 
161
  response = client.chat.completions.create(
162
- model=model_name or "gpt-4o",
163
  messages=[{"role": "user", "content": prompt}],
164
  temperature=0.3,
165
  response_format={"type": "json_object"}
166
  )
167
- return {**json.loads(response.choices[0].message.content), "available": True, "provider": "OPENAI"}
168
-
169
- def _get_hf_analysis(data: dict, model_name: str) -> dict:
170
- api_token = os.getenv("HF_TOKEN") or os.getenv("PowerGrid") or os.getenv("HUGGING_FACE_HUB_TOKEN")
171
- if not api_token: raise ValueError("Hugging Face token not found (expected HF_TOKEN or PowerGrid secret).")
172
 
173
- model = model_name or HF_MODEL
174
- api_url = f"https://api-inference.huggingface.co/models/{model}"
175
- headers = {"Authorization": f"Bearer {api_token}"}
176
- prompt = _build_prompt(data) + "\nJSON Output:"
177
-
178
- response = requests.post(api_url, headers=headers, json={
179
- "inputs": prompt,
180
- "parameters": {"max_new_tokens": 1000, "return_full_text": False}
181
- })
182
-
183
- if response.status_code != 200:
184
- raise ValueError(f"HF API Error: {response.text}")
185
-
186
- # Extract JSON string from response
187
- try:
188
- res_json = response.json()
189
- if isinstance(res_json, list) and len(res_json) > 0:
190
- text = res_json[0].get('generated_text', '')
191
- else:
192
- text = str(res_json)
193
-
194
- if "```json" in text:
195
- text = text.split("```json")[1].split("```")[0]
196
- elif "```" in text:
197
- text = text.split("```")[1].split("```")[0]
198
-
199
- return {**json.loads(text.strip()), "available": True, "provider": "HF"}
200
- except:
201
- raise ValueError("Failed to parse JSON from Hugging Face model response")
202
 
203
  def get_llm_analysis(data: dict, provider: str = "GEMINI", model_name: str = None) -> dict:
204
- """Main entry point for LLM analysis with explicit provider support."""
205
  try:
 
206
  if provider == "GEMINI":
207
- return _get_gemini_analysis(data)
 
208
  elif provider == "QWEN":
209
- return _get_hf_analysis(data, model_name or "Qwen/Qwen2.5-72B-Instruct")
210
  elif provider == "OPENAI":
211
- return _get_openai_analysis(data, model_name or "gpt-4o")
 
212
  elif provider == "HF":
213
- return _get_hf_analysis(data, model_name)
 
 
 
 
 
 
214
  except Exception as e:
215
  error_msg = str(e)
216
- # If the user specifically requested a model and it failed, tell them why.
217
  return {
218
  **_FALLBACK_BASE,
219
  "available": False,
220
  "summary": f"Evaluation Failed: {error_msg}",
221
  "error": error_msg,
222
- "detailed_analysis": f"The requested {provider} analysis could not be completed. \n\nReason: {error_msg}\n\nPlease check your Hugging Face Space secrets settings."
223
  }
224
-
225
- # Global fallback logic (only if provider was None/Unknown, which shouldn't happen now)
226
- return _get_heuristic_analysis(data)
 
1
  """
2
+ LLM Evaluator – analyzes BESS-RL evaluation results using the Hugging Face Router.
3
  Includes a heuristic fallback for when API quotas are exceeded.
4
+ All models (Gemma, Qwen, GPT) are routed via the Hugging Face OpenAI-compatible API.
5
  """
6
  import os
7
  import json
8
  import requests
9
+ import openai
10
 
11
+ # Default Model IDs for the HF Router
12
+ DEFAULT_GEMMA_MODEL = os.getenv("HF_GEMMA_MODEL", "google/gemma-4-31b-it")
13
+ DEFAULT_QWEN_MODEL = os.getenv("HF_QWEN_MODEL", "Qwen/Qwen2.5-72B-Instruct")
14
+ DEFAULT_GPT_MODEL = os.getenv("HF_GPT_MODEL", "openai/gpt-4o-mini")
15
+
16
+ TASK_DESCRIPTIONS = {
17
+ "easy": "Energy Arbitrage only (buy cheap, sell expensive)",
18
+ "medium": "Energy Arbitrage + Frequency Regulation",
19
+ "hard": "Energy Arbitrage + Frequency Regulation + Peak Shaving",
20
+ }
21
 
22
  _FALLBACK_BASE = {
23
  "available": False,
 
34
  "provider": "UNKNOWN"
35
  }
36
 
 
 
 
 
 
 
37
  def _get_heuristic_analysis(data: dict) -> dict:
38
  """Provides a rule-based assessment when LLMs are unavailable."""
39
  scores = data.get("scores", {})
40
  overall = scores.get("overall", 0)
41
  task = data.get("task", "hard")
42
 
 
43
  if overall >= 0.85: verdict = "Excellent"
44
  elif overall >= 0.70: verdict = "Good"
45
  elif overall >= 0.50: verdict = "Needs Improvement"
46
  else: verdict = "Poor"
47
 
48
  strengths, weaknesses, recommendations = [], [], []
 
 
49
  if scores.get("reward", 0) > 0.8: strengths.append("Strong reward optimization")
50
  else: weaknesses.append("Sub-optimal profit generation")
51
 
 
60
  weaknesses.append("Aggressive battery cycling")
61
  recommendations.append("Increase degradation cost coefficient to preserve battery health")
62
 
 
 
63
  h_score = (
64
  scores.get("reward", 0) * 0.4 +
65
  scores.get("soc_readiness", 0) * 0.2 +
 
124
  }}
125
  """
126
 
127
+ def _get_router_analysis(data: dict, model_id: str) -> dict:
128
+ """Calls the Hugging Face Router (OpenAI-compatible) for LLM analysis."""
129
+ api_token = os.getenv("HF_TOKEN") or os.getenv("PowerGrid") or os.getenv("HUGGING_FACE_HUB_TOKEN")
130
+ if not api_token:
131
+ raise ValueError("Hugging Face token not found (expected HF_TOKEN).")
132
 
133
+ # Initialize OpenAI client pointing to HF Router
134
+ client = openai.OpenAI(
135
+ base_url="https://router.huggingface.co/v1",
136
+ api_key=api_token
 
 
 
 
 
 
137
  )
 
 
 
 
 
 
 
 
 
 
 
 
138
 
 
 
139
  prompt = _build_prompt(data)
140
 
141
  response = client.chat.completions.create(
142
+ model=model_id,
143
  messages=[{"role": "user", "content": prompt}],
144
  temperature=0.3,
145
  response_format={"type": "json_object"}
146
  )
 
 
 
 
 
147
 
148
+ content = response.choices[0].message.content
149
+ return {**json.loads(content), "available": True, "provider": f"HF:{model_id}"}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
 
151
  def get_llm_analysis(data: dict, provider: str = "GEMINI", model_name: str = None) -> dict:
152
+ """Main entry point for LLM analysis. Routes all providers through HF Router."""
153
  try:
154
+ # Map provider to specific model ID on HF Router
155
  if provider == "GEMINI":
156
+ # Using Gemma 4 as the replacement for Gemini
157
+ model_id = model_name or DEFAULT_GEMMA_MODEL
158
  elif provider == "QWEN":
159
+ model_id = model_name or DEFAULT_QWEN_MODEL
160
  elif provider == "OPENAI":
161
+ # Routing OpenAI requests through HF Router as requested
162
+ model_id = model_name or DEFAULT_GPT_MODEL
163
  elif provider == "HF":
164
+ model_id = model_name or DEFAULT_GEMMA_MODEL
165
+ else:
166
+ # Fallback for unknown providers
167
+ model_id = model_name or DEFAULT_GEMMA_MODEL
168
+
169
+ return _get_router_analysis(data, model_id)
170
+
171
  except Exception as e:
172
  error_msg = str(e)
 
173
  return {
174
  **_FALLBACK_BASE,
175
  "available": False,
176
  "summary": f"Evaluation Failed: {error_msg}",
177
  "error": error_msg,
178
+ "detailed_analysis": f"The requested {provider} analysis could not be completed using model {model_id if 'model_id' in locals() else 'unknown'}.\n\nReason: {error_msg}\n\nPlease check your Hugging Face Space secrets and token permissions."
179
  }