Update app.py
Browse files
app.py
CHANGED
@@ -330,139 +330,232 @@ try:
|
|
330 |
except Exception as e:
|
331 |
print(f"[ERROR] Workflow execution failed: {e}")
|
332 |
|
333 |
-
|
334 |
-
|
335 |
-
from typing import Dict
|
336 |
-
from pydantic import BaseModel
|
337 |
-
from langgraph.graph import StateGraph, END
|
338 |
-
from langchain_core.prompts import PromptTemplate
|
339 |
-
from langchain_core.messages import HumanMessage
|
340 |
-
from langchain_huggingface import HuggingFacePipeline
|
341 |
from transformers import pipeline, AutoTokenizer, AutoModelForCausalLM
|
|
|
|
|
|
|
|
|
|
|
342 |
import gradio as gr
|
343 |
|
344 |
-
#
|
345 |
-
#
|
346 |
-
#
|
347 |
-
#print(a)
|
348 |
-
|
349 |
-
# Define HuggingFace LLM
|
350 |
def create_llm():
|
351 |
model_name = "Qwen/Qwen2.5-7B-Instruct-1M"
|
352 |
tokenizer = AutoTokenizer.from_pretrained(model_name)
|
353 |
model = AutoModelForCausalLM.from_pretrained(model_name)
|
|
|
354 |
llm_pipeline = pipeline(
|
355 |
task="text-generation",
|
356 |
model=model,
|
357 |
tokenizer=tokenizer,
|
358 |
-
device
|
359 |
-
max_new_tokens=
|
360 |
)
|
361 |
return HuggingFacePipeline(pipeline=llm_pipeline)
|
362 |
|
363 |
-
#
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
368 |
|
369 |
-
|
|
|
|
|
|
|
370 |
registered_visitors = [{"visitor_name": "John Doe", "visitor_mobile": "1234567890"}]
|
371 |
-
|
372 |
v["visitor_name"] == visitor_name and v["visitor_mobile"] == visitor_mobile
|
373 |
for v in registered_visitors
|
374 |
)
|
375 |
-
return {"registered": is_registered}
|
376 |
-
|
377 |
-
def scheduling_agent(scheduling_details: Dict[str, str]) -> Dict[str, str]:
|
378 |
-
"""Schedule an appointment."""
|
379 |
-
doctor_name = scheduling_details.get("doctor_name")
|
380 |
-
department_name = scheduling_details.get("department_name")
|
381 |
|
382 |
-
|
383 |
-
|
384 |
-
return
|
385 |
|
386 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
387 |
class VisitorState(BaseModel):
|
388 |
visitor_name: str = ""
|
389 |
visitor_mobile: str = ""
|
|
|
390 |
doctor_name: str = ""
|
391 |
department_name: str = ""
|
|
|
392 |
messages: list = []
|
|
|
|
|
393 |
|
394 |
-
def input_state(state: VisitorState)
|
395 |
-
"""
|
396 |
-
return {"messages": ["Please provide your name
|
397 |
|
398 |
-
def registration_state(state: VisitorState)
|
399 |
-
"""State
|
400 |
-
|
401 |
-
|
402 |
-
)
|
403 |
-
if result["registered"]:
|
404 |
return {"messages": ["Visitor is registered."], "next": "SchedulingState"}
|
405 |
else:
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
]
|
417 |
-
"next":
|
418 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
419 |
|
420 |
-
#
|
|
|
|
|
421 |
workflow = StateGraph(VisitorState)
|
|
|
|
|
422 |
workflow.add_node("InputState", input_state)
|
423 |
workflow.add_node("RegistrationState", registration_state)
|
424 |
workflow.add_node("SchedulingState", scheduling_state)
|
|
|
|
|
425 |
|
426 |
# Define edges
|
427 |
workflow.add_edge("InputState", "RegistrationState")
|
428 |
-
workflow.
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
END: END,
|
434 |
-
}
|
435 |
-
)
|
436 |
workflow.set_entry_point("InputState")
|
437 |
compiled_graph = workflow.compile()
|
438 |
|
439 |
-
#
|
440 |
-
|
441 |
-
|
|
|
|
|
442 |
state = VisitorState(
|
443 |
visitor_name=visitor_name,
|
444 |
visitor_mobile=visitor_mobile,
|
|
|
445 |
doctor_name=doctor_name,
|
446 |
department_name=department_name,
|
447 |
)
|
448 |
-
|
449 |
# Execute workflow
|
450 |
result = compiled_graph.invoke(state.dict())
|
451 |
-
return result["messages"]
|
452 |
|
453 |
iface = gr.Interface(
|
454 |
fn=gradio_interface,
|
455 |
inputs=[
|
456 |
gr.Textbox(label="Visitor Name"),
|
457 |
gr.Textbox(label="Visitor Mobile Number"),
|
|
|
458 |
gr.Textbox(label="Doctor Name"),
|
459 |
gr.Textbox(label="Department Name"),
|
460 |
],
|
461 |
outputs="textbox",
|
462 |
)
|
463 |
|
|
|
464 |
if __name__ == "__main__":
|
465 |
iface.launch()
|
466 |
|
467 |
-
'''
|
468 |
|
|
|
|
330 |
except Exception as e:
|
331 |
print(f"[ERROR] Workflow execution failed: {e}")
|
332 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
333 |
from transformers import pipeline, AutoTokenizer, AutoModelForCausalLM
|
334 |
+
from langchain_huggingface import HuggingFacePipeline
|
335 |
+
from langchain.tools import Tool
|
336 |
+
from langchain.agents import create_react_agent
|
337 |
+
from langgraph.graph import StateGraph, END
|
338 |
+
from pydantic import BaseModel
|
339 |
import gradio as gr
|
340 |
|
341 |
+
# ---------------------------------------
|
342 |
+
# Step 1: Define Hugging Face LLM (Qwen/Qwen2.5-7B-Instruct-1M)
|
343 |
+
# ---------------------------------------
|
|
|
|
|
|
|
344 |
def create_llm():
|
345 |
model_name = "Qwen/Qwen2.5-7B-Instruct-1M"
|
346 |
tokenizer = AutoTokenizer.from_pretrained(model_name)
|
347 |
model = AutoModelForCausalLM.from_pretrained(model_name)
|
348 |
+
|
349 |
llm_pipeline = pipeline(
|
350 |
task="text-generation",
|
351 |
model=model,
|
352 |
tokenizer=tokenizer,
|
353 |
+
device=-1, # CPU mode, set to 0 for GPU
|
354 |
+
max_new_tokens=200
|
355 |
)
|
356 |
return HuggingFacePipeline(pipeline=llm_pipeline)
|
357 |
|
358 |
+
# ---------------------------------------
|
359 |
+
# Step 2: Create Agents
|
360 |
+
# ---------------------------------------
|
361 |
+
llm = create_llm()
|
362 |
+
|
363 |
+
# Registration Agent
|
364 |
+
registration_agent = Tool(
|
365 |
+
name="registration_check",
|
366 |
+
description="Check if a patient is registered.",
|
367 |
+
func=lambda details: registration_tool(details.get("visitor_name"), details.get("visitor_mobile"))
|
368 |
+
)
|
369 |
+
|
370 |
+
# Scheduling Agent
|
371 |
+
scheduling_agent = Tool(
|
372 |
+
name="schedule_appointment",
|
373 |
+
description="Fetch available time slots for a doctor.",
|
374 |
+
func=lambda details: doctor_slots_tool(details.get("doctor_name"))
|
375 |
+
)
|
376 |
+
|
377 |
+
# Payment Agent
|
378 |
+
payment_agent = Tool(
|
379 |
+
name="process_payment",
|
380 |
+
description="Generate a payment link and confirm the payment.",
|
381 |
+
func=lambda details: confirm_payment_tool(details.get("transaction_id"))
|
382 |
+
)
|
383 |
+
|
384 |
+
# Email Agent
|
385 |
+
email_agent = Tool(
|
386 |
+
name="send_email",
|
387 |
+
description="Send appointment confirmation email to the visitor.",
|
388 |
+
func=lambda details: email_tool(
|
389 |
+
details.get("visitor_email"),
|
390 |
+
details.get("appointment_details"),
|
391 |
+
details.get("hospital_location")
|
392 |
+
)
|
393 |
+
)
|
394 |
|
395 |
+
# ---------------------------------------
|
396 |
+
# Step 3: Tools and Mock Functions
|
397 |
+
# ---------------------------------------
|
398 |
+
def registration_tool(visitor_name: str, visitor_mobile: str) -> bool:
|
399 |
registered_visitors = [{"visitor_name": "John Doe", "visitor_mobile": "1234567890"}]
|
400 |
+
return any(
|
401 |
v["visitor_name"] == visitor_name and v["visitor_mobile"] == visitor_mobile
|
402 |
for v in registered_visitors
|
403 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
404 |
|
405 |
+
def register_visitor(visitor_name: str, visitor_mobile: str) -> bool:
|
406 |
+
"""Register a new user if not already registered."""
|
407 |
+
return True # Simulate successful registration
|
408 |
|
409 |
+
def doctor_slots_tool(doctor_name: str):
|
410 |
+
available_slots = {
|
411 |
+
"Dr. Smith": ["10:00 AM", "2:00 PM"],
|
412 |
+
"Dr. Brown": ["12:00 PM"]
|
413 |
+
}
|
414 |
+
return available_slots.get(doctor_name, [])
|
415 |
+
|
416 |
+
def payment_tool(amount: float):
|
417 |
+
"""Generate a payment link."""
|
418 |
+
return f"http://mock-payment-link.com/pay?amount={amount}"
|
419 |
+
|
420 |
+
def confirm_payment_tool(transaction_id: str) -> dict:
|
421 |
+
"""Confirm the payment."""
|
422 |
+
if transaction_id == "TIMEOUT":
|
423 |
+
return {"status": "FAILED", "reason_code": "timeout"}
|
424 |
+
elif transaction_id == "SUCCESS":
|
425 |
+
return {"status": "SUCCESS", "reason_code": None}
|
426 |
+
else:
|
427 |
+
return {"status": "FAILED", "reason_code": "other_error"}
|
428 |
+
|
429 |
+
def email_tool(visitor_email: str, appointment_details: str, hospital_location: str) -> bool:
|
430 |
+
"""Simulate sending an email to the visitor with appointment details."""
|
431 |
+
print(f"Sending email to {visitor_email}...")
|
432 |
+
print(f"Appointment Details: {appointment_details}")
|
433 |
+
print(f"Hospital Location: {hospital_location}")
|
434 |
+
# Simulate success
|
435 |
+
return True
|
436 |
+
|
437 |
+
# ---------------------------------------
|
438 |
+
# Step 4: Define Workflow States
|
439 |
+
# ---------------------------------------
|
440 |
class VisitorState(BaseModel):
|
441 |
visitor_name: str = ""
|
442 |
visitor_mobile: str = ""
|
443 |
+
visitor_email: str = ""
|
444 |
doctor_name: str = ""
|
445 |
department_name: str = ""
|
446 |
+
selected_slot: str = ""
|
447 |
messages: list = []
|
448 |
+
payment_confirmed: bool = False
|
449 |
+
email_sent: bool = False
|
450 |
|
451 |
+
def input_state(state: VisitorState):
|
452 |
+
"""InputState: Collect visitor details."""
|
453 |
+
return {"messages": ["Please provide your name, mobile number, and email."], "next": "RegistrationState"}
|
454 |
|
455 |
+
def registration_state(state: VisitorState):
|
456 |
+
"""Registration State: Check and register visitor."""
|
457 |
+
is_registered = registration_tool(state.visitor_name, state.visitor_mobile)
|
458 |
+
if is_registered:
|
|
|
|
|
459 |
return {"messages": ["Visitor is registered."], "next": "SchedulingState"}
|
460 |
else:
|
461 |
+
successfully_registered = register_visitor(state.visitor_name, state.visitor_mobile)
|
462 |
+
if successfully_registered:
|
463 |
+
return {"messages": ["Visitor has been successfully registered."], "next": "SchedulingState"}
|
464 |
+
else:
|
465 |
+
return {"messages": ["Registration failed. Please try again later."], "next": END}
|
466 |
+
|
467 |
+
def scheduling_state(state: VisitorState):
|
468 |
+
"""SchedulingState: Fetch available slots for a doctor."""
|
469 |
+
available_slots = doctor_slots_tool(state.doctor_name)
|
470 |
+
if available_slots:
|
471 |
+
state.selected_slot = available_slots[0]
|
472 |
+
return {"messages": [f"Slot selected for {state.doctor_name}: {state.selected_slot}"], "next": "PaymentState"}
|
473 |
+
else:
|
474 |
+
return {"messages": [f"No available slots for {state.doctor_name}."], "next": END}
|
475 |
+
|
476 |
+
def payment_state(state: VisitorState):
|
477 |
+
"""PaymentState: Generate payment link and confirm."""
|
478 |
+
payment_link = payment_tool(500)
|
479 |
+
state.messages.append(f"Please proceed to pay at: {payment_link}")
|
480 |
+
|
481 |
+
# Simulate payment confirmation
|
482 |
+
payment_response = confirm_payment_tool("SUCCESS")
|
483 |
+
if payment_response["status"] == "SUCCESS":
|
484 |
+
state.payment_confirmed = True
|
485 |
+
return {"messages": ["Payment successful. Appointment is being finalized."], "next": "FinalState"}
|
486 |
+
elif payment_response["reason_code"] == "timeout":
|
487 |
+
return {"messages": ["Payment timed out. Retrying payment..."], "next": "PaymentState"}
|
488 |
+
else:
|
489 |
+
return {"messages": ["Payment failed due to an error. Please try again later."], "next": END}
|
490 |
+
|
491 |
+
def final_state(state: VisitorState):
|
492 |
+
"""FinalState: Send email confirmation and finalize the appointment."""
|
493 |
+
if state.payment_confirmed:
|
494 |
+
appointment_details = f"Doctor: {state.doctor_name}\nTime: {state.selected_slot}"
|
495 |
+
hospital_location = "123 Main St, Springfield, USA"
|
496 |
+
email_success = email_tool(state.visitor_email, appointment_details, hospital_location)
|
497 |
+
|
498 |
+
if email_success:
|
499 |
+
state.email_sent = True
|
500 |
+
return {"messages": [f"Appointment confirmed. Details sent to your email: {state.visitor_email}"], "next": END}
|
501 |
+
else:
|
502 |
+
return {"messages": ["Appointment confirmed, but failed to send email. Please contact support."], "next": END}
|
503 |
+
else:
|
504 |
+
return {"messages": ["Payment confirmation failed. Appointment could not be finalized."], "next": END}
|
505 |
|
506 |
+
# ---------------------------------------
|
507 |
+
# Step 5: Build Langgraph Workflow
|
508 |
+
# ---------------------------------------
|
509 |
workflow = StateGraph(VisitorState)
|
510 |
+
|
511 |
+
# Add nodes
|
512 |
workflow.add_node("InputState", input_state)
|
513 |
workflow.add_node("RegistrationState", registration_state)
|
514 |
workflow.add_node("SchedulingState", scheduling_state)
|
515 |
+
workflow.add_node("PaymentState", payment_state)
|
516 |
+
workflow.add_node("FinalState", final_state)
|
517 |
|
518 |
# Define edges
|
519 |
workflow.add_edge("InputState", "RegistrationState")
|
520 |
+
workflow.add_edge("RegistrationState", "SchedulingState")
|
521 |
+
workflow.add_edge("SchedulingState", "PaymentState")
|
522 |
+
workflow.add_edge("PaymentState", "FinalState")
|
523 |
+
|
524 |
+
# Entry Point
|
|
|
|
|
|
|
525 |
workflow.set_entry_point("InputState")
|
526 |
compiled_graph = workflow.compile()
|
527 |
|
528 |
+
# ---------------------------------------
|
529 |
+
# Step 6: Gradio Interface
|
530 |
+
# ---------------------------------------
|
531 |
+
def gradio_interface(visitor_name, visitor_mobile, visitor_email, doctor_name, department_name):
|
532 |
+
"""Interface for Gradio application."""
|
533 |
state = VisitorState(
|
534 |
visitor_name=visitor_name,
|
535 |
visitor_mobile=visitor_mobile,
|
536 |
+
visitor_email=visitor_email,
|
537 |
doctor_name=doctor_name,
|
538 |
department_name=department_name,
|
539 |
)
|
|
|
540 |
# Execute workflow
|
541 |
result = compiled_graph.invoke(state.dict())
|
542 |
+
return "\n".join(result["messages"])
|
543 |
|
544 |
iface = gr.Interface(
|
545 |
fn=gradio_interface,
|
546 |
inputs=[
|
547 |
gr.Textbox(label="Visitor Name"),
|
548 |
gr.Textbox(label="Visitor Mobile Number"),
|
549 |
+
gr.Textbox(label="Visitor Email"),
|
550 |
gr.Textbox(label="Doctor Name"),
|
551 |
gr.Textbox(label="Department Name"),
|
552 |
],
|
553 |
outputs="textbox",
|
554 |
)
|
555 |
|
556 |
+
# Execute the Gradio interface
|
557 |
if __name__ == "__main__":
|
558 |
iface.launch()
|
559 |
|
|
|
560 |
|
561 |
+
'''
|