sha6th commited on
Commit
1347aae
·
1 Parent(s): 1be5e4e

Clean FastAPI evaluation endpoints

Browse files
Files changed (1) hide show
  1. main.py +122 -39
main.py CHANGED
@@ -1,60 +1,133 @@
1
  from fastapi import FastAPI, HTTPException
2
  from pydantic import BaseModel
3
  from typing import List
4
- from src.database import init_db, save_evaluation
5
  import traceback
6
- from src.aggregator import evaluate_all, evaluate_generation_only
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
 
8
  app = FastAPI(
9
  title="LLM Evaluation & Hallucination Detection Framework",
10
  version="2.0.0"
11
  )
12
 
 
 
 
 
 
13
  class EvalRequest(BaseModel):
14
  question: str
15
  retrieved_contexts: List[str]
16
  llm_response: str
17
 
18
- class EvalResponse(BaseModel):
19
- final_verdict: str
20
- retrieval_evaluation: dict
21
- generation_evaluation: dict
22
 
23
  class LLMOnlyEvalRequest(BaseModel):
24
  question: str
25
  context: str
26
  llm_response: str
27
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  @app.post("/evaluate", response_model=EvalResponse)
29
  def evaluate(request: EvalRequest):
 
 
 
 
 
30
  if not request.question.strip():
31
- raise HTTPException(status_code=400, detail="Question cannot be empty")
 
 
 
 
32
  if not request.retrieved_contexts:
33
- raise HTTPException(status_code=400, detail="Retrieved contexts cannot be empty")
 
 
 
 
34
  if not request.llm_response.strip():
35
- raise HTTPException(status_code=400, detail="LLM response cannot be empty")
 
 
 
36
 
37
  try:
 
 
 
 
 
38
  result = evaluate_all(
39
  question=request.question,
40
  retrieved_contexts=request.retrieved_contexts,
41
  llm_response=request.llm_response
42
  )
 
 
 
 
 
43
  save_evaluation(
44
- context=" ".join(request.retrieved_contexts),
 
 
45
  question=request.question,
46
  llm_response=request.llm_response,
47
  result=result
48
  )
 
49
  return result
 
50
  except Exception as e:
51
- raise HTTPException(status_code=500, detail=str(e) + "\n" + traceback.format_exc())
52
 
53
- init_db()
 
 
 
 
 
 
 
 
 
 
54
 
55
  @app.post("/evaluate-llm")
56
  def evaluate_llm(request: LLMOnlyEvalRequest):
57
 
 
 
 
 
58
  if not request.question.strip():
59
  raise HTTPException(
60
  status_code=400,
@@ -75,12 +148,20 @@ def evaluate_llm(request: LLMOnlyEvalRequest):
75
 
76
  try:
77
 
 
 
 
 
78
  result = evaluate_generation_only(
79
  question=request.question,
80
  context=request.context,
81
  llm_response=request.llm_response
82
  )
83
 
 
 
 
 
84
  save_evaluation(
85
  context=request.context,
86
  question=request.question,
@@ -94,46 +175,37 @@ def evaluate_llm(request: LLMOnlyEvalRequest):
94
 
95
  raise HTTPException(
96
  status_code=500,
97
- detail=str(e) + "\n" + traceback.format_exc()
 
 
98
  )
99
 
100
 
 
 
 
 
101
  @app.get("/")
102
  def home():
103
- return {"message": "LLM Evaluation Framework v2.0 is running"}
104
 
105
- @app.post("/evaluate", response_model=EvalResponse)
106
- def evaluate(request: EvalRequest):
107
-
108
- if not request.question.strip():
109
- raise HTTPException(status_code=400, detail="Question cannot be empty")
110
- if not request.retrieved_contexts:
111
- raise HTTPException(status_code=400, detail="Retrieved contexts cannot be empty")
112
- if not request.llm_response.strip():
113
- raise HTTPException(status_code=400, detail="LLM response cannot be empty")
114
-
115
- result = evaluate_all(
116
- question=request.question,
117
- retrieved_contexts=request.retrieved_contexts,
118
- llm_response=request.llm_response
119
- )
120
-
121
- save_evaluation(
122
- context=" ".join(request.retrieved_contexts),
123
- question=request.question,
124
- llm_response=request.llm_response,
125
- result=result
126
- )
127
 
128
- return result
129
 
130
- from src.database import get_all_evaluations
 
 
131
 
132
  @app.get("/history")
133
  def history():
 
134
  rows = get_all_evaluations()
 
135
  results = []
 
136
  for row in rows:
 
137
  results.append({
138
  "id": row[0],
139
  "question": row[2],
@@ -141,4 +213,15 @@ def history():
141
  "final_verdict": row[4],
142
  "created_at": row[11]
143
  })
144
- return {"total": len(results), "evaluations": results}
 
 
 
 
 
 
 
 
 
 
 
 
1
  from fastapi import FastAPI, HTTPException
2
  from pydantic import BaseModel
3
  from typing import List
 
4
  import traceback
5
+
6
+ from src.database import (
7
+ init_db,
8
+ save_evaluation,
9
+ get_all_evaluations
10
+ )
11
+
12
+ from src.aggregator import (
13
+ evaluate_all,
14
+ evaluate_generation_only
15
+ )
16
+
17
+
18
+ # =========================================================
19
+ # FastAPI Application
20
+ # =========================================================
21
 
22
  app = FastAPI(
23
  title="LLM Evaluation & Hallucination Detection Framework",
24
  version="2.0.0"
25
  )
26
 
27
+
28
+ # =========================================================
29
+ # Request Models
30
+ # =========================================================
31
+
32
  class EvalRequest(BaseModel):
33
  question: str
34
  retrieved_contexts: List[str]
35
  llm_response: str
36
 
 
 
 
 
37
 
38
  class LLMOnlyEvalRequest(BaseModel):
39
  question: str
40
  context: str
41
  llm_response: str
42
 
43
+
44
+ # =========================================================
45
+ # Response Model for Full RAG Evaluation
46
+ # =========================================================
47
+
48
+ class EvalResponse(BaseModel):
49
+ final_verdict: str
50
+ retrieval_evaluation: dict
51
+ generation_evaluation: dict
52
+
53
+
54
+ # =========================================================
55
+ # Full RAG Evaluation
56
+ # =========================================================
57
+
58
  @app.post("/evaluate", response_model=EvalResponse)
59
  def evaluate(request: EvalRequest):
60
+
61
+ # -----------------------------
62
+ # Validate input
63
+ # -----------------------------
64
+
65
  if not request.question.strip():
66
+ raise HTTPException(
67
+ status_code=400,
68
+ detail="Question cannot be empty"
69
+ )
70
+
71
  if not request.retrieved_contexts:
72
+ raise HTTPException(
73
+ status_code=400,
74
+ detail="Retrieved contexts cannot be empty"
75
+ )
76
+
77
  if not request.llm_response.strip():
78
+ raise HTTPException(
79
+ status_code=400,
80
+ detail="LLM response cannot be empty"
81
+ )
82
 
83
  try:
84
+
85
+ # -----------------------------
86
+ # Full RAG evaluation
87
+ # -----------------------------
88
+
89
  result = evaluate_all(
90
  question=request.question,
91
  retrieved_contexts=request.retrieved_contexts,
92
  llm_response=request.llm_response
93
  )
94
+
95
+ # -----------------------------
96
+ # Save evaluation
97
+ # -----------------------------
98
+
99
  save_evaluation(
100
+ context=" ".join(
101
+ request.retrieved_contexts
102
+ ),
103
  question=request.question,
104
  llm_response=request.llm_response,
105
  result=result
106
  )
107
+
108
  return result
109
+
110
  except Exception as e:
 
111
 
112
+ raise HTTPException(
113
+ status_code=500,
114
+ detail=str(e)
115
+ + "\n"
116
+ + traceback.format_exc()
117
+ )
118
+
119
+
120
+ # =========================================================
121
+ # LLM-ONLY Evaluation
122
+ # =========================================================
123
 
124
  @app.post("/evaluate-llm")
125
  def evaluate_llm(request: LLMOnlyEvalRequest):
126
 
127
+ # -----------------------------
128
+ # Validate input
129
+ # -----------------------------
130
+
131
  if not request.question.strip():
132
  raise HTTPException(
133
  status_code=400,
 
148
 
149
  try:
150
 
151
+ # -----------------------------
152
+ # Generation-only evaluation
153
+ # -----------------------------
154
+
155
  result = evaluate_generation_only(
156
  question=request.question,
157
  context=request.context,
158
  llm_response=request.llm_response
159
  )
160
 
161
+ # -----------------------------
162
+ # Save evaluation
163
+ # -----------------------------
164
+
165
  save_evaluation(
166
  context=request.context,
167
  question=request.question,
 
175
 
176
  raise HTTPException(
177
  status_code=500,
178
+ detail=str(e)
179
+ + "\n"
180
+ + traceback.format_exc()
181
  )
182
 
183
 
184
+ # =========================================================
185
+ # Home
186
+ # =========================================================
187
+
188
  @app.get("/")
189
  def home():
 
190
 
191
+ return {
192
+ "message": "LLM Evaluation Framework v2.0 is running"
193
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194
 
 
195
 
196
+ # =========================================================
197
+ # History
198
+ # =========================================================
199
 
200
  @app.get("/history")
201
  def history():
202
+
203
  rows = get_all_evaluations()
204
+
205
  results = []
206
+
207
  for row in rows:
208
+
209
  results.append({
210
  "id": row[0],
211
  "question": row[2],
 
213
  "final_verdict": row[4],
214
  "created_at": row[11]
215
  })
216
+
217
+ return {
218
+ "total": len(results),
219
+ "evaluations": results
220
+ }
221
+
222
+
223
+ # =========================================================
224
+ # Initialize Database
225
+ # =========================================================
226
+
227
+ init_db()