From 277fcca3d1710d21484c0bcb4239137eec75304a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E6=BD=AE?= Date: Tue, 25 Nov 2025 19:40:50 +0800 Subject: [PATCH] add guideline --- fastapi_app.py | 127 ++++++++++++++++++++++++++++ prompt/guideline_prompt.md | 167 +++++++++++++++++++++++++++++++++++++ 2 files changed, 294 insertions(+) create mode 100644 prompt/guideline_prompt.md diff --git a/fastapi_app.py b/fastapi_app.py index d095b80..b4c736f 100644 --- a/fastapi_app.py +++ b/fastapi_app.py @@ -21,6 +21,7 @@ from fastapi.staticfiles import StaticFiles from fastapi.middleware.cors import CORSMiddleware from file_manager_api import router as file_manager_router from qwen_agent.llm.schema import ASSISTANT, FUNCTION +from qwen_agent.llm.oai import TextChatAtOAI from pydantic import BaseModel, Field # 导入语义检索服务 @@ -1044,6 +1045,115 @@ def process_messages(messages: List[Message], language: Optional[str] = None) -> return final_messages +def extract_guidelines_from_system_prompt(system_prompt: Optional[str]) -> tuple[str, str]: + """从system_prompt中提取```guideline内容并清理原提示词 + + Returns: + tuple[str, str]: (清理后的system_prompt, 提取的guidelines内容) + """ + if not system_prompt: + return "", "" + + # 使用正则表达式提取 ```guideline``` 包裹的内容 + pattern = r'```guideline\s*\n(.*?)\n```' + matches = re.findall(pattern, system_prompt, re.DOTALL) + + guidelines_text = "\n".join(matches).strip() + + # # 从原始system_prompt中删除 ```guideline``` 内容块 + # cleaned_prompt = re.sub(pattern, '', system_prompt, flags=re.DOTALL) + + # # 清理多余的空行 + # cleaned_prompt = re.sub(r'\n\s*\n\s*\n', '\n\n', cleaned_prompt).strip() + + return guidelines_text + + +def format_messages_to_chat_history(messages: List[Dict[str, str]]) -> str: + """将messages格式化为纯文本聊天记录 + + Args: + messages: 消息列表 + + Returns: + str: 格式化的聊天记录 + """ + chat_history = [] + + for message in messages: + role = message.get('role', '') + content = message.get('content', '') + + if role == 'user': + chat_history.append(f"user: {content}") + elif role == 'assistant': + chat_history.append(f"assistant: {content}") + # 忽略其他角色(如function等) + + return "\n".join(chat_history) + + +async def call_guideline_llm(chat_history: str, guidelines_text: str, model_name: str, api_key: str, model_server: str) -> str: + """调用大语言模型处理guideline分析 + + Args: + chat_history: 聊天历史记录 + guidelines_text: 指导原则文本 + model_name: 模型名称 + api_key: API密钥 + model_server: 模型服务器地址 + + Returns: + str: 模型响应结果 + """ + # 读取guideline提示词模板 + try: + with open('./prompt/guideline_prompt.md', 'r', encoding='utf-8') as f: + guideline_template = f.read() + except Exception as e: + print(f"Error reading guideline prompt template: {e}") + return "" + + # 替换模板中的占位符 + system_prompt = guideline_template.replace('{chat_history}', chat_history).replace('{guidelines_text}', guidelines_text) + + # 配置LLM + llm_config = { + 'model': model_name, + 'api_key': api_key, + 'model_server': model_server, # 使用传入的model_server参数 + } + + # 创建LLM实例 + llm_instance = TextChatAtOAI(llm_config) + + # 调用模型 + messages = [{'role': 'user', 'content': system_prompt}] + + try: + # 设置stream=False来获取非流式响应 + response = llm_instance.chat(messages=messages, stream=False) + + # 处理响应 + if isinstance(response, list) and response: + # 如果返回的是Message列表,提取内容 + if hasattr(response[0], 'content'): + return response[0].content + elif isinstance(response[0], dict) and 'content' in response[0]: + return response[0]['content'] + + # 如果是字符串,直接返回 + if isinstance(response, str): + return response + + # 处理其他类型 + return str(response) if response else "" + + except Exception as e: + print(f"Error calling guideline LLM: {e}") + return "" + + async def create_agent_and_generate_response( bot_id: str, api_key: str, @@ -1064,6 +1174,23 @@ async def create_agent_and_generate_response( if generate_cfg is None: generate_cfg = {} + # 1. 从system_prompt提取guideline内容 + guidelines_text = extract_guidelines_from_system_prompt(system_prompt) + + # 2. 如果有guideline内容,调用LLM进行分析 + guideline_analysis = "" + if guidelines_text: + chat_history = format_messages_to_chat_history(messages) + guideline_analysis = await call_guideline_llm(chat_history, guidelines_text, model_name, api_key, model_server) + print(f"Guideline analysis result: {guideline_analysis}") + + # 将分析结果添加到最后一个消息的内容中 + if guideline_analysis and messages: + last_message = messages[-1] + if last_message.get('role') == 'user': + messages[-1]['content'] += f"\n\nActive Guidelines:\n{guideline_analysis}\nPlease follow these guidelines in your response." + print(messages[-1]['content']) + # 从全局管理器获取或创建助手实例 agent = await agent_manager.get_or_create_agent( bot_id=bot_id, diff --git a/prompt/guideline_prompt.md b/prompt/guideline_prompt.md new file mode 100644 index 0000000..d162587 --- /dev/null +++ b/prompt/guideline_prompt.md @@ -0,0 +1,167 @@ +GENERAL INSTRUCTIONS +----------------- +In our system, the behavior of a conversational AI agent is guided by "guidelines". +Each guideline is composed of two parts: +- "condition": This is a natural-language condition that specifies when a guideline should apply +- "action": This is a natural-language instruction that should be followed by the agent + +Task Description +---------------- +Your task is to evaluate the relevance and applicability of a set of provided 'when' conditions +to the most recent state of an interaction between yourself (an AI agent) and a user. + + +Examples of Guideline Match Evaluations: +``` + 示例 1: 旅游咨询 + + Example #1: ### + - **Chat History**: + user: Hi, I'm planning a trip to Italy next month. What can I do there? + ai_agent: That sounds exciting! I can help you with that. Do you prefer exploring cities or enjoying scenic landscapes? + user: Can you help me figure out the best time to visit Rome and what to pack? + user: Actually I'm also wondering — do I need any special visas or documents as an American citizen? + + - **Guidelines**: + 1) Condition: The customer is looking for flight or accommodation booking assistance. Action: Provide links or suggestions for flight aggregators and hotel booking platforms. + 2) Condition: The customer ask for activities recommendations. Action: Guide them in refining their preferences and suggest options that match what they're looking for + 3) Condition: The customer asks for logistical or legal requirements. Action: Provide a clear answer or direct them to a trusted official source if uncertain. + + - **Expected Result**: + ```json + { + "checks": [ + { + "guideline_id": "", + "condition": "The customer is looking for flight or accommodation booking assistance", + "rationale": "There's no mention of booking logistics like flights or hotels", + "applies": false + }, + { + "guideline_id": "", + "condition": "The customer ask for activities recommendations", + "rationale": "The customer has moved from seeking activity recommendations to asking about legal requirements. Since they are no longer pursuing their original inquiry about activities, this represents a new topic rather than a sub-issue", + "applies": false + }, + { + "guideline_id": "", + "condition": "The customer asks for logistical or legal requirements.", + "rationale": "The customer now asked about visas and documents which are legal requirements", + "applies": true + } + ] + } + ``` + 示例 2: 课程咨询 + + Example #2: ### + - **Chat History**: + user:Hi, I'm interested in your Python programming course, but I'm not sure if I'm ready for it. + ai_agent:Happy to help! Could you share a bit about your background or experience with programming so far? + user:I've done some HTML and CSS, but never written real code before. + ai_agent:Thanks for sharing! That gives me a good idea. Our Python course is beginner-friendly, but it does assume you're comfortable with logic and problem solving. Would you like me to recommend a short prep course first? + user:That sounds useful. But I'm also wondering — is the course self-paced? I work full time. + + - **Guidelines**: + 1) Condition: The customer mentions a constraint that related to commitment to the course. Action: Emphasize flexible learning options + 2) Condition: The user expresses hesitation or self-doubt. Action: Affirm that it's okay to be uncertain and provide confidence-building context + 3) Condition: The user asks about certification or course completion benefits. Action: Clearly explain what the user receives + + - **Expected Result**: + ```json + { + "checks": [ + { + "guideline_id": "", + "condition": "The customer mentions a constraint that related to commitment to the course", + "rationale": "In the most recent message the customer mentions that they work full time which is a constraint", + "applies": true + }, + { + "guideline_id": "", + "condition": "The user expresses hesitation or self-doubt.", + "rationale": "In the most recent message the user still sounds hesitating about their fit to the course", + "applies": true + }, + { + "guideline_id": "", + "condition": "The user asks about certification or course completion benefits.", + "rationale": "The user didn't ask about certification or course completion benefits", + "applies": false + } + ] + } + ``` + + 示例 3: 登录问题 + + Example #3: ### + - **Chat History**: + user:I'm having trouble logging into my account. + ai_agent:I'm sorry to hear that. Can you tell me what happens when you try to log in? + user:It says my password is incorrect. + ai_agent:Have you tried resetting your password? + user:Yes, I did, but I can't access my mail to complete the reset. + + - **Guidelines**: + 1) Condition When the user is having a problem with login. Action: Help then identify the problem and solve it + + - **Expected Result**: + ```json + { + "checks": [ + { + "guideline_id": "", + "condition": "When the user is having a problem with login.", + "rationale": "In the most recent message the customer is still pursuing their login problem, making the mail access problem a sub-issue rather than a new topic", + "applies": true + } + ] + } + + 示例 4: 退货政策 + + Example #4: ### + - **Chat History**: + user: Hi, I'm thinking about ordering this coat, but I need to know — what's your return policy? + ai_agent: You can return items within 30 days either in-store or using our prepaid return label. + user: And what happens if I already wore it once? + + - **Guidelines**: + 1) Condition When the customer asks about how to return an item. Action: Mention both in-store and delivery service return options. + + - **Expected Result**: + ```json + { + "checks": [ + { + "guideline_id": "", + "condition": "When the customer asks about how to return an item.", + "rationale": "In the most recent message the customer asks about what happens when they wore the item, which an inquiry regarding returning an item", + "applies": true + } + ] + } +``` + + +Chat History: +{chat_history} + +Guidelines List: +{guidelines_text} + +OUTPUT FORMAT: +Please specify the applicability of each guideline: +```json +{{ + "checks": [ + {{ + "guideline_id": "1", + "condition": "具体的条件描述", + "rationale": "<解释为什么条件满足或不满足>", + "applies": true/false + }} + ] +}} +```