from langchain_openai import ChatOpenAI from langchain_core.messages import SystemMessage, HumanMessage from app.tools.product_tools import search_product_by_keyword, search_activity_by_keyword, search_article_by_keyword from app.config import settings from app.monitoring import monitor_agent import json import logging logger = logging.getLogger(__name__) SYSTEM_PROMPT = """你是一个儿童成长营养推荐助手。根据用户的需求和营养标签, 推荐合适的商品、活动或文章。 推荐原则: 1. 首先尝试使用搜索工具查找匹配的内容 2. 如果搜索结果为空, 基于你的知识给出建议 3. 每项推荐必须附带推荐理由 4. 以 JSON 格式输出推荐结果 输出格式: { "items": [ { "source": "tool" 或 "knowledge", "type": "product" / "activity" / "article", "id": 数字, "name": "名称", "description": "描述", "reason": "为什么推荐这个" } ] } """ class RecommendAgent: def __init__(self): self.llm = ChatOpenAI( model=settings.llm_model, api_key=settings.llm_api_key, base_url=settings.llm_base_url, temperature=settings.llm_temperature, ) self.tools = [ search_product_by_keyword, search_activity_by_keyword, search_article_by_keyword, ] self.llm_with_tools = self.llm.bind_tools(self.tools) @monitor_agent("recommend") async def run(self, query: str, tags: list[str], limit: int = 5) -> dict: """执行推荐 Agent, 返回推荐结果""" # 如果传入了 tags, 构造搜索关键词 search_query = query or " ".join(tags) messages = [ SystemMessage(content=SYSTEM_PROMPT), HumanMessage(content=f"用户需求: {search_query}\n最大返回数量: {limit}\n请搜索并推荐合适的内容。"), ] # LangChain Tool calling 自动完成: LLM 决定调哪个 Tool → 工具返回结果 → LLM 组织回答 response = await self.llm_with_tools.ainvoke(messages) # 尝试解析 JSON 输出 content = response.content try: # 提取 JSON 块 if "```json" in content: json_str = content.split("```json")[1].split("```")[0].strip() elif "```" in content: json_str = content.split("```")[1].split("```")[0].strip() else: json_str = content.strip() result = json.loads(json_str) return result except (json.JSONDecodeError, IndexError): # 非 JSON 输出, 包装为文本回答 logger.warning("Agent 输出非 JSON, raw: %s", content[:200]) return {"items": [], "text": content}