munals's picture
Upload 33 files
214f910 verified
from __future__ import annotations
import os
from typing import List
from langchain_core.messages import HumanMessage, SystemMessage
from langchain_groq import ChatGroq
from .models import ItineraryPlan, UserRequest
def get_groq_chat() -> ChatGroq | None:
"""Return a Groq-backed chat model if GROQ_API_KEY is set, else None."""
api_key = os.getenv("GROQ_API_KEY")
if not api_key:
return None
# Deterministic, low-temperature model choice
return ChatGroq(
model="llama-3.1-70b-versatile",
temperature=0.2,
groq_api_key=api_key,
)
def generate_narrative_logs(plan: ItineraryPlan, request: UserRequest) -> List[str]:
"""
Use Groq (if available) to generate a concise, human-readable itinerary guide.
Falls back to deterministic heuristic logs when GROQ_API_KEY is not set.
"""
llm = get_groq_chat()
if llm is None:
logs: List[str] = []
for stop in plan.stops:
logs.append(
f"Between {stop.start_time} and {stop.end_time}, enjoy {stop.attraction_name}. "
f"Expect around {stop.estimated_wait_minutes} minutes of queuing and "
f"approximately {stop.walking_distance_m} meters of walking from the previous stop."
)
return logs
system = SystemMessage(
content=(
"You are Qiddiya Smart Guide, an expert theme-park planner. "
"Given a structured itinerary, write a clear, concise, step-by-step guide. "
"Each step should be on its own line starting with a number and a period "
"(for example: '1. 10:00–10:30 — ...'). Focus on clarity; do not add new rides."
)
)
human = HumanMessage(
content=(
f"Visitor date: {request.visit_date}\n"
f"Start/end: {request.start_time}{request.end_time}\n"
f"Must-do attractions: {', '.join(request.must_do_attractions) or 'none'}\n"
f"Intensity: {request.intensity_preference}, walking tolerance: {request.walking_tolerance}\n\n"
f"Itinerary stops (JSON): {plan.model_dump()['stops']}\n\n"
"Now produce the numbered guide as described."
)
)
result = llm.invoke([system, human])
text = result.content if isinstance(result.content, str) else str(result.content)
lines = [line.strip() for line in text.splitlines() if line.strip()]
return lines