Create app.py
Browse files
app.py
ADDED
|
@@ -0,0 +1,361 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import json
|
| 3 |
+
import re
|
| 4 |
+
import datetime
|
| 5 |
+
import gradio as gr
|
| 6 |
+
import chromadb
|
| 7 |
+
import PyPDF2
|
| 8 |
+
from typing import List, Optional
|
| 9 |
+
from pydantic import BaseModel, Field
|
| 10 |
+
from sentence_transformers import SentenceTransformer
|
| 11 |
+
from smolagents import (
|
| 12 |
+
tool,
|
| 13 |
+
ToolCallingAgent,
|
| 14 |
+
WebSearchTool,
|
| 15 |
+
OpenAIServerModel,
|
| 16 |
+
PromptTemplates,
|
| 17 |
+
PlanningPromptTemplate,
|
| 18 |
+
ManagedAgentPromptTemplate,
|
| 19 |
+
FinalAnswerPromptTemplate
|
| 20 |
+
)
|
| 21 |
+
|
| 22 |
+
# ==========================================
|
| 23 |
+
# 1. SCHEMAS
|
| 24 |
+
# ==========================================
|
| 25 |
+
class ClaimInfo(BaseModel):
|
| 26 |
+
claim_number: str
|
| 27 |
+
policy_number: str
|
| 28 |
+
claimant_name: str
|
| 29 |
+
date_of_loss: str
|
| 30 |
+
loss_description: str
|
| 31 |
+
estimated_repair_cost: float
|
| 32 |
+
vehicle_details: Optional[str] = None
|
| 33 |
+
|
| 34 |
+
class PolicyQueries(BaseModel):
|
| 35 |
+
queries: List[str] = Field(default_factory=list)
|
| 36 |
+
|
| 37 |
+
class PolicyRecommendation(BaseModel):
|
| 38 |
+
policy_section: str
|
| 39 |
+
recommendation_summary: str
|
| 40 |
+
deductible: Optional[float] = None
|
| 41 |
+
settlement_amount: Optional[float] = None
|
| 42 |
+
|
| 43 |
+
class ClaimDecision(BaseModel):
|
| 44 |
+
claim_number: str
|
| 45 |
+
covered: bool
|
| 46 |
+
deductible: float
|
| 47 |
+
recommended_payout: float
|
| 48 |
+
notes: Optional[str] = None
|
| 49 |
+
|
| 50 |
+
# ==========================================
|
| 51 |
+
# 2. IMMEDIATE BACKEND INDEXING (Baked-in Knowledge)
|
| 52 |
+
# ==========================================
|
| 53 |
+
embedder = SentenceTransformer('all-MiniLM-L6-v2')
|
| 54 |
+
chroma_client = chromadb.Client()
|
| 55 |
+
collection = chroma_client.get_or_create_collection(name="auto_insurance_policy")
|
| 56 |
+
|
| 57 |
+
def initialize_policy_db():
|
| 58 |
+
policy_file = "policy.pdf"
|
| 59 |
+
if os.path.exists(policy_file) and collection.count() == 0:
|
| 60 |
+
print("Indexing Knowledge Base...")
|
| 61 |
+
with open(policy_file, "rb") as f:
|
| 62 |
+
reader = PyPDF2.PdfReader(f)
|
| 63 |
+
policy_text = "".join([page.extract_text() for page in reader.pages])
|
| 64 |
+
|
| 65 |
+
policy_chunks = policy_text.split("\n\n")
|
| 66 |
+
ids = [f"chunk_{i}" for i in range(len(policy_chunks))]
|
| 67 |
+
embeddings = embedder.encode(policy_chunks).tolist()
|
| 68 |
+
collection.add(documents=policy_chunks, embeddings=embeddings, ids=ids)
|
| 69 |
+
print(f"Knowledge Base Ready: {len(policy_chunks)} chunks indexed.")
|
| 70 |
+
|
| 71 |
+
initialize_policy_db()
|
| 72 |
+
|
| 73 |
+
# Global LLM placeholder for inner tool usage (updated per session)
|
| 74 |
+
llm_model = None
|
| 75 |
+
|
| 76 |
+
# ==========================================
|
| 77 |
+
# 3. CUSTOM TOOLS (Restored & Refined)
|
| 78 |
+
# ==========================================
|
| 79 |
+
@tool
|
| 80 |
+
def parse_claim(json_data: str) -> str:
|
| 81 |
+
"""Parses claim JSON data to validate structure."""
|
| 82 |
+
try:
|
| 83 |
+
data = json.loads(json_data)
|
| 84 |
+
claim_info = ClaimInfo.model_validate(data)
|
| 85 |
+
return claim_info.model_dump_json()
|
| 86 |
+
except Exception as e:
|
| 87 |
+
return f"Error parsing claim: {str(e)}"
|
| 88 |
+
|
| 89 |
+
@tool
|
| 90 |
+
def is_valid_query(query: str) -> str:
|
| 91 |
+
"""Validates policy standing and dates against coverage database."""
|
| 92 |
+
try:
|
| 93 |
+
claim_info = ClaimInfo.model_validate_json(query)
|
| 94 |
+
import csv
|
| 95 |
+
|
| 96 |
+
if not os.path.exists("coverage_data.csv"):
|
| 97 |
+
return json.dumps((False, "System Error: Coverage database not found."))
|
| 98 |
+
|
| 99 |
+
with open("coverage_data.csv", "r") as f:
|
| 100 |
+
reader = csv.DictReader(f)
|
| 101 |
+
policy = next((p for p in reader if p["policy_number"] == claim_info.policy_number), None)
|
| 102 |
+
|
| 103 |
+
if not policy: return json.dumps((False, "Policy not found."))
|
| 104 |
+
|
| 105 |
+
dues = policy.get("claim_dues_remaining", "").lower() in ("true", "1", "yes")
|
| 106 |
+
if dues: return json.dumps((False, "Outstanding dues found."))
|
| 107 |
+
|
| 108 |
+
d_loss = datetime.datetime.strptime(claim_info.date_of_loss, "%Y-%m-%d")
|
| 109 |
+
d_start = datetime.datetime.strptime(policy["coverage_start_date"], "%Y-%m-%d")
|
| 110 |
+
d_end = datetime.datetime.strptime(policy["coverage_end_date"], "%Y-%m-%d")
|
| 111 |
+
|
| 112 |
+
if not (d_start <= d_loss <= d_end):
|
| 113 |
+
return json.dumps((False, "Loss date outside coverage period."))
|
| 114 |
+
|
| 115 |
+
return json.dumps((True, "Valid claim."))
|
| 116 |
+
except Exception as e:
|
| 117 |
+
return f"Error: {str(e)}"
|
| 118 |
+
|
| 119 |
+
@tool
|
| 120 |
+
def generate_policy_queries(claim_info_json: str) -> str:
|
| 121 |
+
"""Generate queries to retrieve relevant policy sections based on claim info."""
|
| 122 |
+
global llm_model
|
| 123 |
+
prompt = f"""
|
| 124 |
+
Analyze the following auto insurance claim to identify 3-5 key policy sections to consult:
|
| 125 |
+
- Focus on collision coverage, liability, deductibles, and relevant exclusions or endorsements.
|
| 126 |
+
- Claim Data: {claim_info_json}
|
| 127 |
+
- Return a JSON object with a 'queries' field containing a list of strings, e.g., {{"queries": ["query1", "query2"]}}. Do not include metadata fields.
|
| 128 |
+
"""
|
| 129 |
+
try:
|
| 130 |
+
messages = [{"role": "user", "content": prompt}]
|
| 131 |
+
response = llm_model(messages)
|
| 132 |
+
response_content = response.content if hasattr(response, 'content') else str(response)
|
| 133 |
+
result = json.loads(response_content)
|
| 134 |
+
return json.dumps(result)
|
| 135 |
+
except Exception as e:
|
| 136 |
+
return f"Error generating policy queries: {str(e)}"
|
| 137 |
+
|
| 138 |
+
@tool
|
| 139 |
+
def retrieve_policy_text(queries_json: str) -> str:
|
| 140 |
+
"""Retrieves policy text from ChromaDB using generated queries."""
|
| 141 |
+
try:
|
| 142 |
+
queries_data = json.loads(queries_json)
|
| 143 |
+
query_strings = queries_data.get("queries", [])
|
| 144 |
+
policy_texts = []
|
| 145 |
+
for q in query_strings:
|
| 146 |
+
query_embedding = embedder.encode([q])[0].tolist()
|
| 147 |
+
results = collection.query(query_embeddings=[query_embedding], n_results=2)
|
| 148 |
+
if results['documents']:
|
| 149 |
+
policy_texts.extend(results['documents'][0])
|
| 150 |
+
return "\n\n".join(set(policy_texts)) # Set removes duplicate chunks
|
| 151 |
+
except Exception as e:
|
| 152 |
+
return f"Error: {str(e)}"
|
| 153 |
+
|
| 154 |
+
@tool
|
| 155 |
+
def generate_recommendation(claim_info_json: str, policy_text: str) -> str:
|
| 156 |
+
"""Generate a policy recommendation based on claim info and retrieved policy text."""
|
| 157 |
+
global llm_model
|
| 158 |
+
prompt = f"""
|
| 159 |
+
Evaluate the following auto insurance claim against the policy text:
|
| 160 |
+
- Determine if the collision is covered, the deductible, settlement amount, and applicable policy section.
|
| 161 |
+
- Claim Info: {claim_info_json}
|
| 162 |
+
- Policy Text: {policy_text}
|
| 163 |
+
- Return a JSON object strictly matching this schema:
|
| 164 |
+
{{
|
| 165 |
+
"policy_section": "str",
|
| 166 |
+
"recommendation_summary": "str",
|
| 167 |
+
"deductible": float or null,
|
| 168 |
+
"settlement_amount": float or null
|
| 169 |
+
}}
|
| 170 |
+
"""
|
| 171 |
+
try:
|
| 172 |
+
messages = [{"role": "user", "content": prompt}]
|
| 173 |
+
response = llm_model(messages)
|
| 174 |
+
response_content = response.content if hasattr(response, 'content') else str(response)
|
| 175 |
+
result = json.loads(response_content)
|
| 176 |
+
PolicyRecommendation.model_validate(result) # Validate structure
|
| 177 |
+
return response_content
|
| 178 |
+
except Exception as e:
|
| 179 |
+
return f"Error generating recommendation: {str(e)}"
|
| 180 |
+
|
| 181 |
+
@tool
|
| 182 |
+
def finalize_decision(claim_info_json: str, recommendation_json: str) -> str:
|
| 183 |
+
"""Finalize the claim decision based on the recommendation and format output."""
|
| 184 |
+
try:
|
| 185 |
+
claim_info = ClaimInfo.model_validate_json(claim_info_json)
|
| 186 |
+
rec_data = json.loads(recommendation_json)
|
| 187 |
+
|
| 188 |
+
# Safe defaults if the model missed a key
|
| 189 |
+
covered = "covered" in rec_data.get("recommendation_summary", "").lower() or (rec_data.get("settlement_amount", 0) or 0) > 0
|
| 190 |
+
deductible = float(rec_data.get("deductible") or 0.0)
|
| 191 |
+
payout = float(rec_data.get("settlement_amount") or 0.0)
|
| 192 |
+
|
| 193 |
+
decision = ClaimDecision(
|
| 194 |
+
claim_number=claim_info.claim_number,
|
| 195 |
+
covered=covered,
|
| 196 |
+
deductible=deductible,
|
| 197 |
+
recommended_payout=payout,
|
| 198 |
+
notes=rec_data.get("recommendation_summary", "No notes provided.")
|
| 199 |
+
)
|
| 200 |
+
return decision.model_dump_json(indent=2)
|
| 201 |
+
except Exception as e:
|
| 202 |
+
return f"Error finalizing decision: {str(e)}"
|
| 203 |
+
|
| 204 |
+
# ==========================================
|
| 205 |
+
# 4. PROMPT TEMPLATES (Restored from notebook)
|
| 206 |
+
# ==========================================
|
| 207 |
+
system_prompt = """
|
| 208 |
+
You are an expert insurance claim-processing agent specializing in auto insurance. You follow a strict, multi-step reasoning process.
|
| 209 |
+
CLAIM PROCESSING ORDER (MANDATORY):
|
| 210 |
+
1. Parse the claim JSON to extract all ClaimInfo fields using `parse_claim`.
|
| 211 |
+
2. Validate the claim using `is_valid_query`. If False, STOP immediately and return an invalid-claim decision.
|
| 212 |
+
3. Generate policy-related search queries based on the extracted claim details using `generate_policy_queries`.
|
| 213 |
+
4. Retrieve relevant policy text from ChromaDB using `retrieve_policy_text`.
|
| 214 |
+
5. Use the web search tool to estimate typical repair costs for the described damage. Compare it to the claimed amount. If unreasonable, reject.
|
| 215 |
+
6. Generate a recommendation using `generate_recommendation`.
|
| 216 |
+
7. Produce the final claim decision using `finalize_decision`.
|
| 217 |
+
ALWAYS follow this exact sequence. Do not reorder, skip, or combine steps.
|
| 218 |
+
"""
|
| 219 |
+
|
| 220 |
+
prompt_templates = PromptTemplates(
|
| 221 |
+
system_prompt=system_prompt,
|
| 222 |
+
planning=PlanningPromptTemplate(
|
| 223 |
+
initial_facts="Claim details:\n{claim_info_json}\nPolicy details:\n{policy_text}",
|
| 224 |
+
initial_plan="Follow the strict claim processing sequence: Parse -> Validate -> Query -> Retrieve -> Web Search Estimate -> Recommend -> Finalize.",
|
| 225 |
+
update_facts_pre_messages="Reassess facts:",
|
| 226 |
+
update_facts_post_messages="Facts updated.",
|
| 227 |
+
update_plan_pre_messages="Revise plan based on new facts:",
|
| 228 |
+
update_plan_post_messages="Plan updated."
|
| 229 |
+
),
|
| 230 |
+
managed_agent=ManagedAgentPromptTemplate(
|
| 231 |
+
task="Process claim: {task_description}",
|
| 232 |
+
report="Generate final decision: {results}"
|
| 233 |
+
),
|
| 234 |
+
final_answer=FinalAnswerPromptTemplate(
|
| 235 |
+
pre_messages="Summarize the final claim decision based on your tools.",
|
| 236 |
+
post_messages="Output clearly formatted decision.",
|
| 237 |
+
final_answer_template="""### ⚖️ Final Adjudication Result\n\n{final_answer}"""
|
| 238 |
+
)
|
| 239 |
+
)
|
| 240 |
+
|
| 241 |
+
# ==========================================
|
| 242 |
+
# 5. STATELESS PROCESSING GATEKEEPER
|
| 243 |
+
# ==========================================
|
| 244 |
+
def ui_process_claim(api_key, base_url, claim_no, policy_no, name, date, cost, vehicle, desc):
|
| 245 |
+
"""Gatekeeper: validates API key and structures data safely before AI processing."""
|
| 246 |
+
if not api_key or not api_key.startswith("sk-"):
|
| 247 |
+
return "### ❌ Error\nPlease provide a valid OpenAI API Key in the Settings tab."
|
| 248 |
+
|
| 249 |
+
payload = {
|
| 250 |
+
"claim_number": claim_no,
|
| 251 |
+
"policy_number": policy_no,
|
| 252 |
+
"claimant_name": name,
|
| 253 |
+
"date_of_loss": date,
|
| 254 |
+
"loss_description": desc,
|
| 255 |
+
"estimated_repair_cost": cost,
|
| 256 |
+
"vehicle_details": vehicle
|
| 257 |
+
}
|
| 258 |
+
|
| 259 |
+
return execute_agent_workflow(api_key, base_url, json.dumps(payload))
|
| 260 |
+
|
| 261 |
+
def execute_agent_workflow(api_key, base_url, claim_json):
|
| 262 |
+
global llm_model
|
| 263 |
+
os.environ['OPENAI_API_KEY'] = api_key
|
| 264 |
+
os.environ['OPENAI_BASE_URL'] = base_url or "https://api.openai.com/v1"
|
| 265 |
+
|
| 266 |
+
# Initialize stateless model for current user
|
| 267 |
+
llm_model = OpenAIServerModel(
|
| 268 |
+
model_id="gpt-4.1",
|
| 269 |
+
api_base=os.environ['OPENAI_BASE_URL'],
|
| 270 |
+
api_key=os.environ['OPENAI_API_KEY']
|
| 271 |
+
)
|
| 272 |
+
|
| 273 |
+
agent = ToolCallingAgent(
|
| 274 |
+
tools=[
|
| 275 |
+
parse_claim,
|
| 276 |
+
is_valid_query,
|
| 277 |
+
generate_policy_queries,
|
| 278 |
+
retrieve_policy_text,
|
| 279 |
+
generate_recommendation,
|
| 280 |
+
finalize_decision,
|
| 281 |
+
WebSearchTool()
|
| 282 |
+
],
|
| 283 |
+
model=llm_model,
|
| 284 |
+
prompt_templates=prompt_templates,
|
| 285 |
+
add_base_tools=False # Disabled base tools to strictly enforce custom workflow
|
| 286 |
+
)
|
| 287 |
+
|
| 288 |
+
try:
|
| 289 |
+
result = agent.run(f"Process this claim JSON strictly according to the mandatory workflow: {claim_json}")
|
| 290 |
+
return str(result)
|
| 291 |
+
except Exception as e:
|
| 292 |
+
return f"### ❌ Agent Execution Error\n{str(e)}"
|
| 293 |
+
|
| 294 |
+
# ==========================================
|
| 295 |
+
# 6. GRADIO UI (Guided & Anti-Breakage)
|
| 296 |
+
# ==========================================
|
| 297 |
+
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
| 298 |
+
gr.Markdown("# 🚗 Agentic Auto-Insurance Claims Processor")
|
| 299 |
+
gr.Markdown("*The Policy Knowledge Base is initialized and ready. Submit your claim below.*")
|
| 300 |
+
|
| 301 |
+
with gr.Tab("Settings"):
|
| 302 |
+
api_key_input = gr.Textbox(
|
| 303 |
+
label="OpenAI API Key",
|
| 304 |
+
type="password",
|
| 305 |
+
placeholder="sk-...",
|
| 306 |
+
info="Your key is only used for this session."
|
| 307 |
+
)
|
| 308 |
+
base_url_input = gr.Textbox(label="API Base URL (Optional)", value="https://api.openai.com/v1")
|
| 309 |
+
|
| 310 |
+
with gr.Tab("Claim Adjudicator"):
|
| 311 |
+
with gr.Row():
|
| 312 |
+
# Guided User Inputs
|
| 313 |
+
with gr.Column():
|
| 314 |
+
gr.Markdown("### 📝 Claim Details")
|
| 315 |
+
claim_no = gr.Textbox(label="Claim Number", placeholder="CLAIM-100", info="Format: CLAIM-XXX")
|
| 316 |
+
policy_no = gr.Dropdown(
|
| 317 |
+
label="Policy Number",
|
| 318 |
+
choices=["PN-1", "PN-2", "PN-3", "PN-4", "PN-5"],
|
| 319 |
+
info="Select an active policy ID."
|
| 320 |
+
)
|
| 321 |
+
claimant_name = gr.Textbox(label="Claimant Name", placeholder="Jane Doe")
|
| 322 |
+
loss_date = gr.Textbox(label="Date of Loss", placeholder="YYYY-MM-DD", info="Must follow YYYY-MM-DD format.")
|
| 323 |
+
|
| 324 |
+
loss_desc = gr.Textbox(
|
| 325 |
+
label="Loss Description",
|
| 326 |
+
placeholder="Describe the incident...",
|
| 327 |
+
lines=2
|
| 328 |
+
)
|
| 329 |
+
repair_cost = gr.Number(
|
| 330 |
+
label="Estimated Repair Cost ($)",
|
| 331 |
+
value=500.0,
|
| 332 |
+
minimum=0,
|
| 333 |
+
info="Do not use negative values."
|
| 334 |
+
)
|
| 335 |
+
vehicle_info = gr.Textbox(label="Vehicle Details", placeholder="2022 Tesla Model 3")
|
| 336 |
+
|
| 337 |
+
submit_btn = gr.Button("Evaluate Claim", variant="primary")
|
| 338 |
+
|
| 339 |
+
# Decision Output
|
| 340 |
+
with gr.Column():
|
| 341 |
+
gr.Markdown("### ⚖️ Agent Decision")
|
| 342 |
+
output_display = gr.Markdown(value="*Results will appear here after evaluation...*")
|
| 343 |
+
|
| 344 |
+
# Preset Examples Component
|
| 345 |
+
gr.Examples(
|
| 346 |
+
examples=[
|
| 347 |
+
["CLAIM-001", "PN-1", "John Smith", "2023-10-15", 850.0, "2020 Honda Civic", "Front bumper damage from low-speed collision."],
|
| 348 |
+
["CLAIM-002", "PN-3", "Alice Wong", "2024-02-10", 12000.0, "2023 Ford F-150", "Extensive side impact damage from running a red light."],
|
| 349 |
+
],
|
| 350 |
+
inputs=[claim_no, policy_no, claimant_name, loss_date, repair_cost, vehicle_info, loss_desc],
|
| 351 |
+
label="Load Example Claims"
|
| 352 |
+
)
|
| 353 |
+
|
| 354 |
+
submit_btn.click(
|
| 355 |
+
fn=ui_process_claim,
|
| 356 |
+
inputs=[api_key_input, base_url_input, claim_no, policy_no, claimant_name, loss_date, repair_cost, vehicle_info, loss_desc],
|
| 357 |
+
outputs=output_display
|
| 358 |
+
)
|
| 359 |
+
|
| 360 |
+
if __name__ == "__main__":
|
| 361 |
+
demo.launch()
|