背景
Multi-agent结合MCP已经成为非常明确的新一轮发展趋势,但日常工作发现,很多刚接触的小伙伴还在受“如何编写一个能完成自己预期需求的prompt”这一需求而感到困扰。那么结合Multi-agent,我们不妨借助Trae来不自己写一行代码,就能设计和实现一个多智能体合作来自动化完成prompt自动迭代生成的系统,Let's do it!
框架和LLM部署方式选型
不同于我们之前采用langroid的选型,本期我们将采用langchain,这里做出变更的原因主要在于langchain似乎大家使用的更为广泛,但在易用性上本文仍然推荐langroid,感兴趣的小伙伴可以参看我们前一系列中的内容。
-
Multi-Agent: langchain(python)
-
LLM部署(同前一系列):
- 需所选定的Multi-agent框架支持,理论上流行的框架目前都支持类openai的接口方式来接入远程大模型,或者是本地部署的LLM模型,甚至是类似于coze这种直接选取即可。
- 考虑到本地部署模型无合规风险,query无额外限制(如速率限制),且免费,本项目以Ollama部署本地模型为例,进行展示。
- ollma使用 & ollma提供的模型列表
方案设计
workflow
-
用户需求
- 包括用户想要设计一个什么样的prompt
- 针对这个想设计的prompt,用户需提供一个预期输入和相应的预期输出
-
Main Agent
- 根据用户需求和预期输入输出,生成初始Prompt
- 根据反馈迭代Prompt,当超出最大迭代次数或当前调整后的prompt已达成需求,则输出最终prompt
-
Validator Agent
- 读取prompt并加载,以预期输入为输入,得到实际输出,对比预期输出,输出Output差异
-
Analysis Agent
- 分析Output差异,向Main Agent提出针对性的反馈调整意见
从头开始
环境准备
-
部署本地LLM:
-
安装langchain,langgraph等相关依赖
pip3 install -r requirements.txt
requirements.txt为当前项目依赖的python lib信息,如下:
langchain>=0.1.0
langgraph>=0.0.10
langchain-community>=0.0.10
langchain-core>=0.1.0
typing-extensions>=4.8.0
typing>=3.7.4
pydantic>=2.5.0
ollama>=0.1.5
python-dotenv>=1.0.0
Coding
IDE:Trae 或 Trae CN 本文兼具使用Trae的Builder和Chat模式,受限于对话记录较长,此处仅展示部分示例:
-
最初始的需求:
-
迭代:
以下让我们以代码形式来解读最终Trae生成的本文框架:
1.创建工作流:首先让我们按照上述方案设计里的workflow来创建一个工作流
def create_workflow() -> Graph:
workflow = Graph()
# 定义工作流节点
workflow.add_node("generate_prompt", generate_prompt)
workflow.add_node("validate_prompt", validate_prompt)
workflow.add_node("generate_feedback", generate_feedback)
workflow.add_node("check_completion", check_completion)
# 定义工作流边和条件
workflow.add_edge("generate_prompt", "validate_prompt")
workflow.add_edge("validate_prompt", "check_completion")
workflow.add_conditional_edges(
"check_completion",
lambda x: x[0],
{
"continue": "generate_feedback",
"end": END
}
)
workflow.add_edge("generate_feedback", "generate_prompt")
# 设置工作流入口
workflow.set_entry_point("generate_prompt")
return workflow.compile()
2.实现工作流中的关键节点:
- generate_prompt(对应MainAgent):
def generate_prompt(state: WorkflowState) -> WorkflowState:
print("\n🎯 进入生成提示词阶段...")
main_agent = MainAgent()
if len(state["current_prompt"]) == 0:
# 将所有示例传递给主智能体
state["current_prompt"] = main_agent.generate_initial_prompt(
state["user_goal"],
state["examples"]
)
else:
state["current_prompt"] = main_agent.optimize_prompt(
state["feedback"],
state["current_prompt"]
)
return state
- validate_prompt(对应validatorAgent):
def validate_prompt(state: WorkflowState) -> WorkflowState:
print("\n🔍 进入验证提示词阶段...")
validator = ValidatorAgent()
validation_result = validator.validate_output(state["current_prompt"], state["examples"])
# 确保validation_result包含is_acceptable字段
if isinstance(validation_result, dict):
validation_result.setdefault("is_acceptable", False)
else:
validation_result = {"is_acceptable": False, "individual_results": [], "overall_score": 0.0}
state["validation_result"] = validation_result
return state
- generate_feedback(对应AnalysisAgent):
def generate_feedback(state: WorkflowState) -> WorkflowState:
print("\n💭 进入生成反馈阶段...")
feedback_agent = FeedbackAgent()
# 处理check_completion返回的元组状态
if isinstance(state, tuple):
_, state = state
# 确保state是字典类型并包含所有必需键
if not isinstance(state, dict) or not all(key in state for key in ["current_prompt", "validation_result", "feedback", "user_goal", "examples", "iteration_count", "max_retries", "is_complete"]):
print(f"警告:状态对象不完整或不是字典类型,当前状态内容为: {str(state)}")
if hasattr(state, '__dict__'):
state = vars(state)
else:
state = {
"feedback": getattr(state, 'feedback', ""),
"current_prompt": getattr(state, 'current_prompt', ""),
"validation_result": getattr(state, 'validation_result', {}),
"user_goal": getattr(state, 'user_goal', ""),
"examples": getattr(state, 'examples', []),
"iteration_count": getattr(state, 'iteration_count', 0),
"max_retries": getattr(state, 'max_retries', 3),
"is_complete": getattr(state, 'is_complete', False)
}
# 确保所有必需键都存在
for key in ["current_prompt", "validation_result", "feedback", "user_goal", "examples", "iteration_count", "max_retries", "is_complete"]:
if key not in state:
state[key] = "" if key in ["current_prompt", "feedback", "user_goal"] else ([] if key == "examples" else ({} if key == "validation_result" else (0 if key == "iteration_count" else (3 if key == "max_retries" else False))))
try:
# 检查必要的键是否存在
if "current_prompt" not in state or "validation_result" not in state:
print(f"错误:状态对象缺少必要的键")
state["feedback"] = ""
return state
# 检查是否有差异
has_differences = any(
len(result.get('analysis_result', {}).get('differences', [])) > 0
for result in state["validation_result"].get("individual_results", [])
)
feedback = feedback_agent.generate_feedback(
state["current_prompt"],
state["validation_result"]
)
if feedback == "NO_DIFFERENCES":
state["validation_result"]["is_acceptable"] = True
state["is_complete"] = True
return state
state["feedback"] = feedback
except Exception as e:
print(f"错误:生成反馈时发生异常 - {str(e)}")
state["feedback"] = ""
return state
- check_completion(用来检查迭代后的prompt是不是ok,或者超过最大迭代次数了):
def check_completion(state: WorkflowState) -> tuple[str, WorkflowState]:
print("\n✨ 进入完成检查阶段...")
state["iteration_count"] += 1
# 检查验证结果是否为空或无效
if not state.get("validation_result") or not isinstance(state["validation_result"], dict):
print("警告:无效的验证结果")
return ("continue", state)
# 检查是否有差异
has_differences = any(
len(result.get('analysis_result', {}).get('differences', [])) > 0
for result in state["validation_result"].get("individual_results", [])
)
if state["validation_result"]["is_acceptable"] and not has_differences:
state["is_complete"] = True
return ("end", state)
if state["iteration_count"] >= state["max_retries"]:
state["is_complete"] = True
return ("end", state)
return ("continue", state)
3.实现关键Agent处理逻辑:
- Main Agent:
from langchain.agents import AgentExecutor, BaseSingleActionAgent
from langchain_core.prompts import ChatPromptTemplate
from langchain_community.chat_models.ollama import ChatOllama
from langchain.schema import SystemMessage, HumanMessage
from typing import Dict, List, Any, Optional
from langchain.schema import AgentAction
class MainAgent(BaseSingleActionAgent):
llm: ChatOllama = None
initial_template: str = None
optimization_template: str = None
prompt_template: Optional[ChatPromptTemplate] = None
iteration_history: List[Dict[str, Any]] = None
def __init__(self):
super().__init__()
# 推荐换个小一点size参数量的模型,实测下来32G内存的mbp,跑起来还是卡
self.llm = ChatOllama(model='gemma3:27b')
self.iteration_history = []
self.prompt_template = None # 将在具体方法中根据需要选择使用哪个模板
self.initial_template = """您是一个专业的提示词工程师,请严格按照以下要求生成system prompt:
1. 目标分析:
- 深入分析用户目标:{user_goal}
- 识别关键需求和约束条件
- 确保生成的prompt直接服务于目标
- 考虑目标的边界场景和异常情况
- 评估目标的可扩展性和通用性
2. 语义分析:
- 确保prompt语义完整性和清晰度
- 分析上下文关联性和依赖关系
- 识别关键概念和术语
- 考虑领域特定的专业术语和最佳实践
- 确保指令的逻辑性和连贯性
3. 输入输出示例处理:
- 深入分析示例输入:{example_input}
- 分析期望输出:{example_output}
- 提取输入输出的关键特征和模式
- 识别输入输出的边界条件和特殊情况
- 确保prompt能够处理类似的输入场景并生成符合预期的输出格式
4. 质量标准:
- 确保prompt简洁明确系统且结构化,避免冗余
- 使用精确的指令和约束条件
- 保持一致的语言风格和格式
- 确保输出格式与示例输出保持一致
- 考虑prompt的可测试性和可维护性
- 评估prompt的鲁棒性和容错性
请基于以上要求,直接输出一个专业、全面且高质量的system prompt,不要包含任何解释性内容或分析过程。
注意:生成的prompt应当具备良好的扩展性、鲁棒性和一致性,能够处理各种边界场景和异常情况。"""
self.optimization_template = """您是一个专业的提示词工程师,请严格按照以下要求优化system prompt:
当前Prompt:
{example_input}
针对当前Prompt的反馈:
{feedback}
请你按照如下要求分析反馈,优化当前Prompt。
1. 当前Prompt分析:
- 深入分析当前prompt
- 识别现有prompt的优点和不足
- 评估prompt的结构和组织方式
- 检查prompt的语义完整性和清晰度
2. 反馈分析:
- 仔细分析优化反馈
- 识别需要改进的关键点
- 确定优化的优先级和方向
- 考虑反馈的合理性和可行性
3. 优化策略:
- 保持prompt的核心功能和优点
- 针对性地解决反馈中提出的问题
- 确保优化后的prompt更加专业和高效
- 增强prompt的鲁棒性和适应性
4. 质量保证:
- 确保优化后的prompt结构清晰、逻辑严密
- 保持语言风格的一致性和专业性
- 验证优化是否解决了原有问题
- 评估优化后的prompt是否更易于使用和维护
请基于以上要求,直接输出一个经过优化的、更高质量的system prompt,不要包含任何解释性内容或分析过程。
注意:优化后的prompt应当保持原有的优点,同时显著改进已识别的问题。"""
self.prompt_template = None # 将在具体方法中根据需要选择使用哪个模板
@property
def input_keys(self):
return ["user_goal", "example_input", "example_output", "feedback"]
@property
def tool_run_logging_kwargs(self) -> Dict[str, Any]:
return {"handle_tool_error": True}
def plan(self, inputs: Dict[str, str], intermediate_steps: List = None) -> List[Dict[str, Any]]:
return self.aplan(inputs, intermediate_steps)
def generate_initial_prompt(self, user_goal: str, examples: List[Dict[str, str]]) -> str:
"""生成初始的system prompt"""
print("\n🎯 正在生成初始提示词...")
# 格式化所有示例
formatted_examples = []
for i, example in enumerate(examples, 1):
formatted_examples.append(f"示例{i}:\n输入:{example['input']}\n预期输出:{example['expected_output']}")
examples_text = "\n\n".join(formatted_examples)
self.prompt_template = ChatPromptTemplate.from_template(self.initial_template)
messages = self.prompt_template.format(
user_goal=user_goal,
example_input=examples_text,
example_output="" # 不再单独使用example_output
)
response = self.llm.invoke(messages)
return response.content.strip()
def aplan(self, inputs: Dict[str, str], intermediate_steps: List = None) -> List[Dict[str, Any]]:
messages = self.prompt_template.format(
user_goal=inputs["user_goal"],
example_input=inputs["example_input"],
example_output=inputs["example_output"],
feedback=inputs["feedback"]
)
response = self.llm.invoke(messages)
return [AgentAction(
tool="prompt_optimization",
tool_input={"optimized_prompt": response.content},
log=f"Iteration {len(self.iteration_history)+1}"
)]
def optimize_prompt(self, feedback: str, current_prompt: str) -> str:
"""优化当前的system prompt"""
print("\n✨ 正在根据反馈优化提示词...")
self.prompt_template = ChatPromptTemplate.from_template(self.optimization_template)
messages = self.prompt_template.format(
example_input=current_prompt,
feedback=feedback
)
response = self.llm.invoke(messages)
return response.content.strip()
- Validator agent:
from langchain_community.chat_models.ollama import ChatOllama
from langchain_core.messages import SystemMessage, HumanMessage
from typing import Dict
from analysis_agent import AnalysisAgent
class ValidatorAgent:
def __init__(self):
pass
def validate_output(self, system_prompt: str, examples: list) -> Dict:
"""调用模型验证多个示例输出并计算差异"""
print("\n🔄 正在验证模型输出...")
chat = ChatOllama(model='gemma3:27b', temperature=0.2)
all_results = []
for example in examples:
print("📌 验证-输入内容:")
print(example['input'])
messages = [
SystemMessage(content=system_prompt),
HumanMessage(content=example['input'])
]
response = chat.invoke(messages)
actual_output = response.content.strip()
print("\n🔍 输出对比:")
print(f"预期输出: {example['expected_output']}")
print(f"实际输出: {actual_output}")
# 调用分析智能体分析差异
analysis = AnalysisAgent().analyze_diff([{
'actual_output': actual_output,
'expected_output': example['expected_output']
}])
all_results.append({
'input': example['input'],
'actual_output': actual_output,
'expected_output': example['expected_output'],
'analysis_result': analysis
})
# 计算总体评分(基于差异数量和质量)
total_differences = sum(
len(result['analysis_result']['differences'])
for result in all_results
)
# 如果没有差异,评分为1;否则根据差异数量计算(差异越多分数越低)
overall_score = 1.0 if total_differences == 0 else 1.0 / (1 + total_differences)
# 判断是否可接受(评分大于0.7视为可接受)
is_acceptable = overall_score > 0.7
return {
'is_acceptable': is_acceptable,
'individual_results': all_results,
'overall_score': overall_score
}
- Analysis agent:(上述validator agent主要调用analysis agent来识别差异)
from langchain_core.messages import HumanMessage, SystemMessage
from langchain_community.chat_models.ollama import ChatOllama
from typing import Dict
class AnalysisAgent:
llm: ChatOllama = None
def __init__(self):
self.llm = ChatOllama(model='deepseek-r1:14b')
def analyze_diff(self, diff_reports: list) -> Dict:
"""使用结构化prompt进行差异分析"""
print("\n📊 正在分析输出差异...")
system_prompt = """您是一个专业的输出差异分析专家。请分析模型实际输出和预期输出的差异,重点关注以下维度:
1. 内容差异:
- 预期输出中存在但实际输出缺失的内容
- 实际输出中出现但预期输出没有的内容
- 内容的语义一致性和准确性
- 关键信息的完整性和正确性
2. 格式差异:
- 输出格式是否符合预期(如JSON格式、列表格式等)
- 输出结构是否一致
- 格式规范性和标准化程度
请直接指出具体的差异点,每个差异标注类型(内容缺失/内容多余/格式不一致/语义偏差),不要包含任何解释性内容、分析过程或一致的点。
如果没有差异则输出:"无任何差异"。"""
all_differences = []
for i, diff_report in enumerate(diff_reports, 1):
print(f"\n🔍 分析示例 {i}:")
# 验证输入格式
if not isinstance(diff_report, dict) or 'actual_output' not in diff_report or 'expected_output' not in diff_report:
print(f"警告:示例 {i} 的差异报告格式不正确,应为包含actual_output和expected_output的字典")
continue
print("📌 差异报告内容:")
print(f"实际输出: {diff_report['actual_output']}")
print(f"预期输出: {diff_report['expected_output']}")
diff_content = f"实际输出: {diff_report['actual_output']}\n预期输出: {diff_report['expected_output']}"
result = self.llm.invoke([
SystemMessage(content=system_prompt),
HumanMessage(content=f'\n{diff_content}')
])
print("\n🔍 分析结果:")
print(result.content)
if result and hasattr(result, 'content') and result.content:
all_differences.append(result.content)
return {
'analysis_text': '\n'.join(all_differences) if all_differences else '没有发现有效差异',
'differences': all_differences
}
- Feedback agent:
from langchain_community.chat_models.ollama import ChatOllama
from langchain_core.messages import HumanMessage, SystemMessage
from typing import Dict
from langchain_core.prompts import ChatPromptTemplate
class FeedbackAgent:
optimization_history: list = None
llm: ChatOllama = None
def __init__(self):
self.optimization_history = []
self.llm = ChatOllama(model='deepseek-r1:14b')
def generate_feedback(self, current_prompt: str, validation_result: Dict) -> str:
"""基于分析结果生成优化建议"""
print("\n🔍 正在分析验证结果并生成优化建议...")
# 添加类型检查和安全访问逻辑
if not isinstance(validation_result, dict) or 'individual_results' not in validation_result:
print("错误:无效的验证结果格式")
return ""
# 检查是否有差异
has_differences = any(
len(result.get('analysis_result', {}).get('differences', [])) > 0
for result in validation_result['individual_results']
)
if not has_differences:
print("✅ 无任何差异,返回特定字符串")
return "NO_DIFFERENCES"
# 生成每个示例的差异摘要
example_summaries = []
for i, result in enumerate(validation_result['individual_results']):
if not isinstance(result, dict) or 'analysis_result' not in result:
continue
analysis_result = result.get('analysis_result', {})
differences = analysis_result.get('differences', [])
if differences:
print(f"\n📌 示例 {i+1} 差异详情:")
for diff in differences:
if isinstance(diff, str):
print(f"- {diff}")
elif isinstance(diff, dict):
print(f"- {diff.get('description', '')}(类型:{diff.get('type', '')})")
example_summaries.append(f"示例 {i+1} 分析:\n" +
"\n".join([f"- {diff}" if isinstance(diff, str) else
f"- {diff['description']}(类型:{diff['type']})"
for diff in differences])
)
prompt_template = ChatPromptTemplate.from_messages([
SystemMessage(content="""您是一个提示词优化专家,请根据以下维度深入分析并生成专业的优化建议:
1. 语义分析:
- 当前prompt的语义完整性和清晰度
- 上下文关联性和依赖关系
- 关键概念和术语的准确性
- 指令的逻辑性和连贯性
2. 质量评估:
- 验证结果中的关键差异点分析
- prompt的可扩展性和通用性
- 边界场景和异常情况的处理能力
- prompt的鲁棒性和容错性
- 输出的一致性和可预测性
3. 改进建议:
- 具体的优化方向和修改建议
- 如何提高prompt的专业性和全面性
- 如何增强prompt的可测试性和可维护性
- 如何优化prompt的性能和效率
请基于以上维度,直接提供具体的优化建议,不要包含任何解释性内容或分析过程。
特别注意:请综合考虑所有示例的验证结果,找出共性问题和特殊情况。"""),
HumanMessage(content=f"""当前系统提示为:\n{current_prompt}
验证分析结果:
1. 示例分析:
{chr(10).join(example_summaries) if example_summaries else '无差异'}
""")
])
chain = prompt_template | ChatOllama(model='deepseek-r1:14b', temperature=0.5)
response = chain.invoke({})
print("\n💡 优化建议:")
print(response.content)
# 将优化建议添加到历史记录
self.optimization_history.append({
'prompt': current_prompt,
'feedback': response.content,
'validation_result': validation_result
})
return response.content.strip()
4.设计main函数入口,接收用户诉求和预期输入输出,启动整个多agent合作的workflow:
from workflow import run_workflow
def collect_examples():
examples = []
while True:
example_input = input("\n请输入示例输入(输入'q'结束):")
if example_input.lower() == 'q':
break
example_output = input("请输入期望输出:")
examples.append({
"input": example_input,
"expected_output": example_output
})
more = input("\n是否继续添加示例?(y/n):")
if more.lower() != 'y':
break
return examples
def main():
print("\n🚀 启动智能提示词优化系统...")
user_goal = input("请输入您的目标描述:")
print("\n📝 开始收集示例...")
examples = collect_examples()
if not examples:
print("\n⚠️ 未提供任何示例,程序退出")
return
print("\n⚙️ 开始执行优化工作流...")
final_state = run_workflow(user_goal, examples)
print(f"\n=== 执行了 {final_state['iteration_count']} 次迭代 ===")
if final_state['validation_result'].get('is_acceptable', False):
print("\n✅ 验证通过,达到可接受标准")
else:
print("\n⛔ 达到最大迭代次数仍未通过验证")
print("\n🎉 最终优化结果:")
print(final_state['current_prompt'])
if __name__ == "__main__":
main()
让我们来看一下效果
感觉还行小伙伴们可以试试
结语
配合上MCP/Function Calling以及RAG,大有可为哦~冲!冲!冲!
喜欢的话,请给个点赞三连哦(づ ̄ 3 ̄)づ