| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- """旅游AI对话服务 - 专用于回答旅游相关问题的LLM Agent"""
- from typing import Iterator, List
- from ..services.llm_service import get_llm
- # 系统提示词 - 严格限定只回答旅游相关问题
- TRAVEL_AGENT_PROMPT = """你是"Trip Planner Pro"智能旅行助手的AI旅游顾问,一个专业、热情、细致的旅行规划专家。
- ## 你的角色
- 你只回答与**旅游、旅行、出行**相关的问题。包括但不限于:
- 1. 🌍 **目的地推荐** - 根据预算、季节、人群推荐旅行目的地
- 2. 🏛️ **景点介绍** - 景点历史、文化、特色、开放时间、门票信息
- 3. 🍜 **美食推荐** - 各地特色美食、餐厅推荐、饮食文化
- 4. 🏨 **住宿建议** - 酒店、民宿、青旅推荐和预订建议
- 5. 🚗 **交通指南** - 到达方式、当地交通、路线规划建议
- 6. 🌤️ **旅行贴士** - 最佳旅行季节、穿衣建议、注意事项
- 7. 📋 **行程规划建议** - 天数安排、路线组合、节奏把控
- 8. 💰 **预算参考** - 旅行费用估算、省钱技巧
- 9. 🛡️ **安全提示** - 旅行安全、健康建议、保险信息
- 10. 🎒 **行前准备** - 行李清单、证件准备、实用APP推荐
- ## 回答规则
- 1. 只回答与旅游/旅行/出行明确相关的问题。
- 2. 如果用户提出非旅游相关的问题(如编程、数学、政治、医疗建议等),请礼貌地拒绝,并引导回到旅游话题。
- 3. 回答要详细、实用、有温度,提供具体的建议而不是笼统的概括。
- 4. 可以结合你对中国各地旅游资源的了解来回答。
- 5. 当用户提到具体城市时,可以结合该城市的特色来推荐。
- 6. 如果用户的问题比较宽泛,可以主动追问细节(预算、天数、人群等)来提供更有针对性的建议。
- 7. 回答不要提及你是AI或大模型,用"我"来指代自己。
- 8. 回答使用中文,保持友好热情的语调。
- ## 非旅游问题的拒绝模板
- 当用户问非旅游问题时,请这样回复:
- "抱歉,我是专门为您提供旅行建议的AI助手,只能回答与旅游出行相关的问题。如果您有任何旅行方面的疑问,比如目的地推荐、行程规划、景点介绍等,我都很乐意为您解答!😊"
- ## 语气风格
- - 热情友好,像一个经验丰富的旅行达人
- - 回答要有结构,适当使用emoji
- - 给出具体可操作的建议
- - 如果信息不确定,诚实告知并提供查证建议
- """
- class TravelChatService:
- """旅游AI对话服务"""
- def __init__(self):
- self.llm = get_llm()
- def _build_messages(self, user_message: str, history: list = None, profile_message: str = "") -> List[dict]:
- """构建带上下文的对话消息列表"""
- messages = [{"role": "system", "content": TRAVEL_AGENT_PROMPT}]
- # 如果有用户画像消息,作为首条用户消息加入(使用 XML 标签标注)
- if profile_message:
- messages.append({"role": "user", "content": profile_message})
- # 添加历史上下文(取最近20条消息)
- if history:
- for msg in history[-20:]:
- role = msg.get("role", "user")
- content = msg.get("content", "")
- if role in ("user", "assistant"):
- messages.append({"role": role, "content": content})
- # 添加当前用户消息
- messages.append({"role": "user", "content": user_message})
- return messages
- def chat(self, user_message: str, history: list = None, profile_message: str = "") -> str:
- """
- 非流式调用:发送消息给旅游AI并获取回复
- """
- messages = self._build_messages(user_message, history, profile_message)
- try:
- response = self.llm.invoke(messages=messages)
- return response.content if hasattr(response, 'content') else str(response)
- except Exception as e:
- raise RuntimeError(f"AI对话服务调用失败: {str(e)}")
- def chat_stream(self, user_message: str, history: list = None, profile_message: str = "") -> Iterator[str]:
- """
- 流式调用:逐块获取AI回复
- """
- messages = self._build_messages(user_message, history, profile_message)
- try:
- for chunk in self.llm.think(messages=messages):
- yield chunk
- except Exception as e:
- raise RuntimeError(f"AI对话流式调用失败: {str(e)}")
- # 全局实例
- _travel_chat_service = None
- def get_travel_chat_service() -> TravelChatService:
- """获取旅游对话服务实例(单例)"""
- global _travel_chat_service
- if _travel_chat_service is None:
- _travel_chat_service = TravelChatService()
- return _travel_chat_service
|