新增对话语言设置 默认使用英文
This commit is contained in:
@@ -211,7 +211,7 @@ async def chat_stream(request: DeepAgentChatRequest):
|
|||||||
config=current_config,
|
config=current_config,
|
||||||
stream_mode=["updates", "messages", "custom"],
|
stream_mode=["updates", "messages", "custom"],
|
||||||
subgraphs=True,
|
subgraphs=True,
|
||||||
context=Context(use_report=request.use_report),
|
context=Context(use_report=request.use_report, language=request.language),
|
||||||
):
|
):
|
||||||
_, mode, chunks = stream
|
_, mode, chunks = stream
|
||||||
if is_first:
|
if is_first:
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ class DeepAgentChatRequest(BaseModel):
|
|||||||
)
|
)
|
||||||
need_suggestion: float = 0
|
need_suggestion: float = 0
|
||||||
use_report: bool = False # ← 新增:是否使用深度报告
|
use_report: bool = False # ← 新增:是否使用深度报告
|
||||||
|
language: str = "en"
|
||||||
|
|
||||||
|
|
||||||
class HistoryItem(BaseModel):
|
class HistoryItem(BaseModel):
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ from src.core.config import MONGO_URI
|
|||||||
from src.server.deep_agent.agents.researcher import build_researcher_subagent
|
from src.server.deep_agent.agents.researcher import build_researcher_subagent
|
||||||
from src.server.deep_agent.agents.user_profile import user_profile_subagent
|
from src.server.deep_agent.agents.user_profile import user_profile_subagent
|
||||||
from src.server.deep_agent.init_llm import build_main_llm
|
from src.server.deep_agent.init_llm import build_main_llm
|
||||||
from src.server.deep_agent.init_prompt import SYSTEM_BASE_PROMPT, SYSTEM_RULES_PROMPT
|
from src.server.deep_agent.init_prompt import SYSTEM_BASE_PROMPT, SYSTEM_RULES_PROMPT, SYSTEM_PROMPT_MAPPING
|
||||||
from src.server.deep_agent.tools.generate_furniture_sketch import edit_furniture, generate_furniture, edit_quote_upload_furniture
|
from src.server.deep_agent.tools.generate_furniture_sketch import edit_furniture, generate_furniture, edit_quote_upload_furniture
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -33,7 +33,8 @@ checkpointer = MongoDBSaver(
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Context:
|
class Context:
|
||||||
use_report: bool
|
use_report: bool = False
|
||||||
|
language: str = "en"
|
||||||
|
|
||||||
|
|
||||||
@wrap_tool_call
|
@wrap_tool_call
|
||||||
@@ -79,30 +80,79 @@ async def report_control(request: ToolCallRequest, handler: Callable[[ToolCallRe
|
|||||||
|
|
||||||
@dynamic_prompt
|
@dynamic_prompt
|
||||||
def user_role_prompt(request: ModelRequest) -> str:
|
def user_role_prompt(request: ModelRequest) -> str:
|
||||||
"""Generate system prompts based on use-report status."""
|
"""Generate system prompts based on use_report status and language preference."""
|
||||||
use_report = request.runtime.context.use_report
|
use_report = request.runtime.context.use_report
|
||||||
|
language = request.runtime.context.language
|
||||||
|
|
||||||
|
# ==================== 语言控制规则(最高优先级) ====================
|
||||||
|
if language.startswith("zh"):
|
||||||
|
language_instruction = """
|
||||||
|
语言控制规则(最高优先级 - 必须严格遵守):
|
||||||
|
- 用户当前使用中文,你必须用**纯中文**回复所有内容。
|
||||||
|
- 最终回复给用户的消息必须是纯中文,禁止中英混杂。
|
||||||
|
- 内部思考和工具调用可以使用英文,但输出给用户的最终消息必须是纯中文。
|
||||||
|
"""
|
||||||
|
else:
|
||||||
|
# 默认英文(en, en-US, en-GB 等)
|
||||||
|
language_instruction = """
|
||||||
|
Language Instruction (Highest Priority - Must be strictly followed):
|
||||||
|
|
||||||
|
- The user is currently using English. You **must** reply to the user entirely in English.
|
||||||
|
- Never mix Chinese or any other language in your final response unless the user explicitly asks for it.
|
||||||
|
- Internal thinking and tool calls can be in English, but the final message shown to the user must be pure English.
|
||||||
|
- Always respond in a natural, professional, and clear English.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# ==================== 报告功能状态提示 ====================
|
||||||
if use_report:
|
if use_report:
|
||||||
report_status = """
|
if language.startswith("zh"):
|
||||||
|
report_status = """
|
||||||
【报告功能状态】当前 use_report = True
|
【报告功能状态】当前 use_report = True
|
||||||
research-subagent 已完全启用,你可以正常调用 task(subagent="research-subagent") 来生成报告。
|
research-subagent 已完全启用,你可以正常调用 task(subagent="research-subagent") 来生成报告。
|
||||||
"""
|
"""
|
||||||
|
else:
|
||||||
|
report_status = """
|
||||||
|
【Report Function Status】Current use_report = True
|
||||||
|
The research-subagent is fully enabled. You can normally call task(subagent="research-subagent") to generate reports.
|
||||||
|
"""
|
||||||
else:
|
else:
|
||||||
report_status = """
|
if language.startswith("zh"):
|
||||||
|
report_status = """
|
||||||
【报告功能状态】当前 use_report = False (后端实际状态为禁用)
|
【报告功能状态】当前 use_report = False (后端实际状态为禁用)
|
||||||
|
|
||||||
核心规则(必须严格遵守):
|
核心规则(必须严格遵守):
|
||||||
- research-subagent 当前不可用,**绝对不要**尝试调用它。
|
- research-subagent 当前不可用,**绝对不要**尝试调用它。
|
||||||
- 当用户说“已开启”、“我已经打开按钮”、“现在可以生成报告了吧”等类似话语时:
|
- 当用户说“已开启”、“我已经打开按钮”、“现在可以生成报告了吧”等类似话语时:
|
||||||
1. 不要立即相信用户的声明。
|
1. 不要立即相信用户的声明。
|
||||||
2. 友好地请求用户确认,并引导重新操作:
|
2. 友好地请求用户确认,并引导重新操作。
|
||||||
“我这边检测到报告功能还没有启用。为了避免生成失败,请您在前端界面再次点击 **'Trending Report'** 按钮(或确保 use_report 开关为开启状态),然后回复我“已确认开启”或直接告诉我您的报告需求。”
|
3. 如果用户坚持说已开启,可以礼貌回复引导确认。
|
||||||
3. 如果用户坚持说已开启,可以回复:
|
|
||||||
“为了确保正常工作,我需要您确认按钮已成功开启。您可以刷新页面后再次点击按钮,然后告诉我具体报告内容,我会马上处理。”
|
|
||||||
- 只有当后端 use_report 真正变为 True 时,才能调用 research-subagent。
|
- 只有当后端 use_report 真正变为 True 时,才能调用 research-subagent。
|
||||||
"""
|
"""
|
||||||
|
else:
|
||||||
|
report_status = """
|
||||||
|
【Report Function Status】Current use_report = False (Actually disabled on the backend)
|
||||||
|
|
||||||
final_prompt = SYSTEM_BASE_PROMPT + report_status + SYSTEM_RULES_PROMPT
|
Core Rules (Must be strictly followed):
|
||||||
logger.info(f"Dynamic prompt generated | use_report={use_report} | report_status injected")
|
- The research-subagent is currently unavailable. **Never** attempt to call it.
|
||||||
|
- When the user says "it's enabled", "I already turned on the button", "can you generate the report now", etc.:
|
||||||
|
1. Do not immediately trust the user's statement.
|
||||||
|
2. Politely ask the user to confirm and guide them to re-operate.
|
||||||
|
3. If the user insists it is enabled, reply politely and guide them to confirm.
|
||||||
|
- Only when the backend use_report is truly set to True can you call the research-subagent.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# ==================== 最终 Prompt 拼接 ====================
|
||||||
|
final_prompt = (
|
||||||
|
language_instruction
|
||||||
|
+ "\n\n"
|
||||||
|
+ SYSTEM_BASE_PROMPT
|
||||||
|
+ report_status
|
||||||
|
+ SYSTEM_RULES_PROMPT
|
||||||
|
)
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
f"Dynamic prompt generated | use_report={use_report} | language={language}"
|
||||||
|
)
|
||||||
|
|
||||||
return final_prompt
|
return final_prompt
|
||||||
|
|
||||||
@@ -135,11 +185,11 @@ def build_main_agent(workspace_dir, enable_thinking):
|
|||||||
)
|
)
|
||||||
main_agent = create_deep_agent(
|
main_agent = create_deep_agent(
|
||||||
model=build_main_llm(enable_thinking=enable_thinking),
|
model=build_main_llm(enable_thinking=enable_thinking),
|
||||||
store=InMemoryStore(),
|
# store=InMemoryStore(),
|
||||||
subagents=subagents,
|
subagents=subagents,
|
||||||
checkpointer=checkpointer,
|
# checkpointer=checkpointer,
|
||||||
tools=[edit_furniture, generate_furniture, edit_quote_upload_furniture],
|
tools=[edit_furniture, generate_furniture, edit_quote_upload_furniture],
|
||||||
backend=backend,
|
# backend=backend,
|
||||||
context_schema=Context,
|
context_schema=Context,
|
||||||
middleware=middleware,
|
middleware=middleware,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -11,13 +11,13 @@ llm = ChatQwen(
|
|||||||
api_key=settings.QWEN_API_KEY
|
api_key=settings.QWEN_API_KEY
|
||||||
)
|
)
|
||||||
|
|
||||||
title_llm = ChatQwen(
|
qwen_plus_llm = ChatQwen(
|
||||||
model="qwen-plus",
|
model="qwen-plus",
|
||||||
max_tokens=3_000,
|
max_tokens=3_000,
|
||||||
timeout=None,
|
timeout=None,
|
||||||
max_retries=2,
|
max_retries=2,
|
||||||
streaming=False,
|
streaming=False,
|
||||||
temperature=0.1,
|
temperature=0.25,
|
||||||
top_p=0.8,
|
top_p=0.8,
|
||||||
api_key=settings.QWEN_API_KEY
|
api_key=settings.QWEN_API_KEY
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -11,6 +11,31 @@ SYSTEM_BASE_PROMPT = """
|
|||||||
2. research-subagent
|
2. research-subagent
|
||||||
负责生成完整报告、调研、总结、分析。
|
负责生成完整报告、调研、总结、分析。
|
||||||
"""
|
"""
|
||||||
|
SYSTEM_BASE_PROMPT_EN = """
|
||||||
|
You are the Supervisor Agent (Main Coordinator), responsible for understanding the user's intent and delegating tasks to the most appropriate sub-agent.
|
||||||
|
|
||||||
|
There are two specialized sub-agents in the system:
|
||||||
|
|
||||||
|
1. **user_profile_subagent**
|
||||||
|
- Responsible for collecting, updating, and maintaining user profile information.
|
||||||
|
- Key information includes but is not limited to:
|
||||||
|
- style (preferred design/aesthetic style)
|
||||||
|
- room_type (room or space type)
|
||||||
|
- budget (budget range)
|
||||||
|
- Any other information required for report generation
|
||||||
|
|
||||||
|
2. **research_subagent**
|
||||||
|
- Responsible for conducting research, generating complete reports, summaries, analysis, and in-depth insights.
|
||||||
|
|
||||||
|
Your primary responsibilities:
|
||||||
|
- Analyze the user's request carefully.
|
||||||
|
- Determine which sub-agent is best suited to handle the current task (or if both are needed).
|
||||||
|
- Delegate the task clearly to the chosen sub-agent(s).
|
||||||
|
- Coordinate between sub-agents when necessary.
|
||||||
|
- Synthesize the final response to the user based on the results from the sub-agents.
|
||||||
|
|
||||||
|
Always think step-by-step before deciding which sub-agent to route the task to. Do not perform the specialized work yourself — delegate it properly.
|
||||||
|
"""
|
||||||
|
|
||||||
SYSTEM_RULES_PROMPT = """
|
SYSTEM_RULES_PROMPT = """
|
||||||
========================
|
========================
|
||||||
@@ -31,8 +56,8 @@ SYSTEM_RULES_PROMPT = """
|
|||||||
**关键参数规则(必须严格遵守)**:
|
**关键参数规则(必须严格遵守)**:
|
||||||
- 调用 `generate_furniture` 或 `edit_quote_upload_furniture` 时,`prompts` 参数**必须是 list[str]**,即使只有一条提示词,也要写成列表形式。
|
- 调用 `generate_furniture` 或 `edit_quote_upload_furniture` 时,`prompts` 参数**必须是 list[str]**,即使只有一条提示词,也要写成列表形式。
|
||||||
正确示例:
|
正确示例:
|
||||||
prompts = ["Generate a traditional Chinese style rattan chair with intricate woven patterns..."]
|
prompts = ["A classic professional hand-drawn furniture concept sketch..."]
|
||||||
错误示例:prompts = "Generate a traditional Chinese style..." (这是字符串,会导致错误!)
|
错误示例:prompts = "A classic..." (这是字符串,会导致错误!)
|
||||||
|
|
||||||
- `image_paths`(如果需要)也必须是 list[str]。
|
- `image_paths`(如果需要)也必须是 list[str]。
|
||||||
|
|
||||||
@@ -55,7 +80,7 @@ SYSTEM_RULES_PROMPT = """
|
|||||||
|
|
||||||
【3】当用户请求报告 / 调研 / 分析 / 总结时:
|
【3】当用户请求报告 / 调研 / 分析 / 总结时:
|
||||||
先判断是否已经具备足够的用户画像信息。
|
先判断是否已经具备足够的用户画像信息。
|
||||||
如果用户需求信息不足(例如缺少风格、房间类型、预算、主题、范围等):
|
如果用户需求信息不足(例如缺少风格、房间类型、主题、范围等):
|
||||||
→ 调用 user_profile_subagent 收集信息
|
→ 调用 user_profile_subagent 收集信息
|
||||||
不要直接生成报告。
|
不要直接生成报告。
|
||||||
如果用户画像信息已经完整:
|
如果用户画像信息已经完整:
|
||||||
@@ -64,7 +89,7 @@ SYSTEM_RULES_PROMPT = """
|
|||||||
【5】用户画像优先级规则
|
【5】用户画像优先级规则
|
||||||
只要用户输入包含以下情况:
|
只要用户输入包含以下情况:
|
||||||
- 表达设计需求
|
- 表达设计需求
|
||||||
- 提供偏好信息(例如风格、预算、房间类型)
|
- 提供偏好信息(例如风格、房间类型)
|
||||||
- 修改之前的偏好
|
- 修改之前的偏好
|
||||||
- 补充报告信息
|
- 补充报告信息
|
||||||
都应该优先调用:
|
都应该优先调用:
|
||||||
@@ -83,6 +108,85 @@ user_profile_subagent
|
|||||||
- 任何 http 开头的图片链接(除非系统明确要求)
|
- 任何 http 开头的图片链接(除非系统明确要求)
|
||||||
所有图片展示均由系统统一处理,你只需负责正确调用工具。
|
所有图片展示均由系统统一处理,你只需负责正确调用工具。
|
||||||
"""
|
"""
|
||||||
|
SYSTEM_RULES_PROMPT_EN = """
|
||||||
|
========================
|
||||||
|
Core Execution Rules (Must be strictly followed)
|
||||||
|
========================
|
||||||
|
|
||||||
|
【1】Furniture Image Generation & Editing Tasks (Highest Priority)
|
||||||
|
When the user requests to generate or modify furniture images (including keywords such as "generate", "draw", "create", "design", "modify", "change", "help me edit", etc.):
|
||||||
|
|
||||||
|
- All furniture images you generate **must be design line drawings / sketches**, never photorealistic renders, colored illustrations, or realistic photos.
|
||||||
|
- Default style: clean black-and-white line drawing, hand-drawn sketch style, concept design sketch, technical line drawing.
|
||||||
|
- Always use line-drawing-specific prompts. Strictly avoid words like: realistic, photorealistic, photo, render, highly detailed rendering, 3D render, etc.
|
||||||
|
- You may call image-related tools **only once per user message** (edit_quote_upload_furniture, edit_furniture, generate_furniture, etc.). Do not call them multiple times.
|
||||||
|
- The generation tool can produce a **maximum of 12 images per call**.
|
||||||
|
- Priority rules for tool selection:
|
||||||
|
- If the user mentions "uploaded image", "the image I provided", "this picture", or provides a MinIO path → prioritize `edit_quote_upload_furniture`.
|
||||||
|
- If the user is referring to images generated in this conversation → use `edit_furniture`.
|
||||||
|
|
||||||
|
**Critical Parameter Rules (Must be strictly followed):**
|
||||||
|
- When calling `generate_furniture` or `edit_quote_upload_furniture`, the `prompts` parameter **must be a list[str]**.
|
||||||
|
Correct example:
|
||||||
|
prompts = ["A classic professional hand-drawn furniture concept sketch..."]
|
||||||
|
Incorrect example: prompts = "A classic..." (This is a string and will cause errors!)
|
||||||
|
|
||||||
|
- The `image_paths` parameter (when required) must also be a **list[str]**.
|
||||||
|
|
||||||
|
**Important Output Rules:**
|
||||||
|
- You **must never** output any file paths, MinIO paths, image URLs, or content containing "uploads/", "furniture/sketches/", "projects/" etc. in your replies to the user.
|
||||||
|
- All images will be displayed to the user through the system interface. You are not allowed to show or mention any paths.
|
||||||
|
- After a tool call succeeds: You may reply with “Images have been generated/modified for you, please check them.” or simply return no message (let the system display the images).
|
||||||
|
- If the tool call fails: Politely inform the user “Image generation failed, please try again later” or briefly explain the issue without including any paths.
|
||||||
|
|
||||||
|
【2】Correct Way to Call Image Tools
|
||||||
|
- Always call image tools **once** per turn. Do not split into multiple calls.
|
||||||
|
- Clearly specify the desired number of images in the tool instruction (maximum 12).
|
||||||
|
- Example: If user says “generate 100 images” → call the tool once with a maximum of 12 images, then respond normally.
|
||||||
|
|
||||||
|
**Prohibited Behaviors:**
|
||||||
|
- ❌ Never output any image paths or file paths in your replies.
|
||||||
|
- ❌ Never call generation tools multiple times to increase quantity.
|
||||||
|
- ❌ Never tell the user any file paths.
|
||||||
|
- ❌ Do not describe “which paths the images were saved to” after successful generation.
|
||||||
|
|
||||||
|
【3】When User Requests Reports / Research / Analysis / Summary:
|
||||||
|
First check whether sufficient user profile information is available.
|
||||||
|
- If key information is missing (e.g., style, room type, theme, scope, etc.):
|
||||||
|
→ Call `user_profile_subagent` to collect the necessary information.
|
||||||
|
Do **not** generate the report directly.
|
||||||
|
- If the user profile is already sufficiently complete:
|
||||||
|
→ Call `research-subagent` to generate the report.
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
【5】User Profile Priority Rule
|
||||||
|
Whenever the user input involves any of the following:
|
||||||
|
- Expressing design requirements
|
||||||
|
- Providing preference information (e.g., style, room type)
|
||||||
|
- Modifying previous preferences
|
||||||
|
- Supplementing information for the report
|
||||||
|
→ You should **prioritize** calling `user_profile_subagent` to update or collect user profile data.
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
【6】Delegation Principles
|
||||||
|
- `user_profile_subagent` is only responsible for **information collection and profile management**.
|
||||||
|
- `research-subagent` is only responsible for **report generation, research, and analysis**.
|
||||||
|
Do not mix their responsibilities.
|
||||||
|
|
||||||
|
========================
|
||||||
|
Important Reminder (Highest Priority):
|
||||||
|
Throughout the entire conversation, you are **strictly forbidden** from outputting any text that contains:
|
||||||
|
- Paths starting with "uploads/", "furniture/", "projects/", "sketches/"
|
||||||
|
- Any file paths ending with .png, .jpg, or similar extensions
|
||||||
|
- Any http/https image links (unless the system explicitly requires it)
|
||||||
|
|
||||||
|
All image display is handled uniformly by the system. You are only responsible for correctly calling the tools.
|
||||||
|
"""
|
||||||
|
|
||||||
|
SYSTEM_PROMPT_MAPPING = {
|
||||||
|
"SYSTEM_BASE_PROMPT_en": SYSTEM_BASE_PROMPT_EN,
|
||||||
|
"SYSTEM_RULES_PROMPT_en": SYSTEM_RULES_PROMPT_EN
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def build_painter_prompt():
|
def build_painter_prompt():
|
||||||
@@ -170,7 +274,7 @@ def build_researcher_prompt():
|
|||||||
你是一名专业的家具设计研究员。你的任务是:
|
你是一名专业的家具设计研究员。你的任务是:
|
||||||
|
|
||||||
【0】获取用户画像:
|
【0】获取用户画像:
|
||||||
- 首先调用 get_user_profile 工具,获取当前用户画像信息(如风格、房间类型、预算等)。
|
- 首先调用 get_user_profile 工具,获取当前用户画像信息(如风格、房间类型等)。
|
||||||
- 根据用户画像,生成五个与用户需求和偏好高度相关的研究词条。
|
- 根据用户画像,生成五个与用户需求和偏好高度相关的研究词条。
|
||||||
|
|
||||||
【1】关键词拆解:
|
【1】关键词拆解:
|
||||||
@@ -205,7 +309,6 @@ def build_user_persona_prompt():
|
|||||||
你的任务是从用户对话中理解并提取报告画像信息,包括但不限于:
|
你的任务是从用户对话中理解并提取报告画像信息,包括但不限于:
|
||||||
- style(装修风格)
|
- style(装修风格)
|
||||||
- room_type(房间类型)
|
- room_type(房间类型)
|
||||||
- budget(预算)
|
|
||||||
|
|
||||||
工作流程:
|
工作流程:
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
from langchain_core.messages import HumanMessage, AIMessage
|
from langchain_core.messages import HumanMessage, AIMessage
|
||||||
from langchain_core.prompts import PromptTemplate
|
|
||||||
|
|
||||||
from src.server.deep_agent.init_llm import title_llm
|
from src.server.deep_agent.init_llm import qwen_plus_llm
|
||||||
|
|
||||||
|
|
||||||
async def conversation_title(agent, config):
|
async def conversation_title(agent, config):
|
||||||
@@ -34,7 +33,7 @@ async def conversation_title(agent, config):
|
|||||||
2. 语言简洁、符合中文表达习惯
|
2. 语言简洁、符合中文表达习惯
|
||||||
3. 仅返回标题,不要额外解释
|
3. 仅返回标题,不要额外解释
|
||||||
"""
|
"""
|
||||||
response = await title_llm.ainvoke(prompt)
|
response = await qwen_plus_llm.ainvoke(prompt)
|
||||||
title = response.content.strip()
|
title = response.content.strip()
|
||||||
|
|
||||||
# 去掉可能的符号
|
# 去掉可能的符号
|
||||||
|
|||||||
Reference in New Issue
Block a user