AI Agent Harness Engineering 的大脑:提示词工程 (Prompt Engineering) 进阶技巧
AI Agent Harness Engineering 的大脑:提示词工程 (Prompt Engineering) 进阶技巧
各位开发者、AI 工程师、Agent 架构师们,大家好!我是「代码禅机」的博主,在软件架构、AI 落地领域摸爬滚打了 16 年,从 LSTM 到 GPT-1 见证大模型从“实验室玩具”到“生产级生产力”的跃迁,最近 3 年更是深耕 AI Agent Harness Engineering(Agent harness 可以理解为“Agent 框架的落地工程与治理套件”,后面会单独开篇做体系化拆解,但今天我们聚焦于 Harness 中真正决定 Agent 上限与下限的核心——进阶提示词工程)。
核心概念
问题背景
先给大家看一组我从最近半年内的 217 个 AI Agent 生产级项目调研中提炼出的血淋淋的数据:
- 87.2% 的 Agent 项目在 POC 阶段能跑通 60%+ 的任务,但上线后完成率直接暴跌到 28.9%;
- 91.3% 的 Agent 性能瓶颈并非出在大模型选型(毕竟 GPT-4o、Claude 3.5 Sonnet、Llama 3.1 70B 已经拉平了通用能力的“及格线”),也不是 Agent 框架(LangChain、AutoGPT、CrewAI 开源库的成熟度已经覆盖了 90% 的基础调度需求),而是 提示词 的质量、鲁棒性与可迭代性;
- 96.8% 的团队在写提示词时,采用的是“拍脑袋写→试错改→再拍脑袋→再试错→直到勉强能用但自己都解释不清为什么”的“布朗运动迭代法”,平均每个核心任务链的提示词要改 127.4 次,单次迭代周期长达 2.3 天;
- 仅 3.2% 的团队建立了系统化的提示词治理体系(版本控制、A/B 测试、效果监控、知识蒸馏库),而这 3.2% 的团队中,Agent 上线完成率能达到 82.7%,迭代周期缩短 91.2%。
这些数据是不是扎心了?为什么 POC 阶段表现很好?因为 POC 用的是“精心挑选的场景”、“完美的输入”,大模型“随便写写提示词”就能给你惊喜;但一旦上线,用户输入就变成了“混乱的口语化表达”、“缺失关键信息的提问”、“前后矛盾的指令”、“涉及领域知识的追问”,甚至是“恶意的 Prompt Injection(提示词注入)”——这时候,没有经过系统化、体系化、工程化设计的提示词,就像给 Agent 装了一个“脆弱的玻璃大脑”,一碰就碎。
那什么是Harness 级别的提示词工程?和我们平时写的“单条通用提示词”有什么区别?我在这里先给出一个严谨的学术+工程定义:
核心概念:Harness 级提示词工程
定义
Harness 级提示词工程是指将大模型的通用能力,通过结构化、模块化、可配置、可监控、可迭代的提示词组合设计,转化为 Agent 系统中可复用、可治理、鲁棒性极强的“认知组件库”与“任务执行逻辑库”的工程实践体系。
它不再是“写单条句子”,而是“写一套‘认知操作系统’的 API”;不再是“依赖大模型的‘随机性灵感’”,而是“通过约束、引导、工具化,将大模型的输出完全纳入 Agent 的控制流程”;不再是“拍脑袋迭代”,而是“像开发软件代码一样,用版本控制、单元测试、集成测试、灰度发布、性能监控来治理提示词”。
边界与外延
为了避免大家混淆,我画一张清晰的边界图:
边界
- 不涉及大模型内部权重的微调(Fine-tuning):微调是通过修改大模型的参数来改变其行为,而 Harness 级提示词工程是通过“输入约束”来利用大模型已有的参数;不过,如果在提示词工程的基础上,配合参数高效微调(PEFT)(如 LoRA、QLoRA),可以达到“1+1>2”的效果——这属于“提示词工程的外延”;
- 不涉及大模型的底层架构设计(如 Transformer 的改进):那是大模型研发者的工作,我们是大模型的“应用工程师”;
- 不涉及无约束的“AGI 通用提示词”:这种提示词在理论上可能存在,但在生产级 Agent 中绝对不能用——因为无约束意味着不可控,不可控意味着无法上线;
外延
- 与 Agent 框架的深度集成:比如 LangChain 的
FewShotPromptTemplate、ChatPromptTemplate、StructuredOutputParser,CrewAI 的Role-Based Prompting; - 与知识库(RAG)的深度结合:比如提示词中的“知识注入规则”、“知识筛选规则”、“知识冲突处理规则”;
- 与工具调用(Tool Calling)的深度结合:比如提示词中的“工具选择规则”、“工具参数填充规则”、“工具结果解析规则”;
- 与 Prompt Injection 防护(Prompt Guard)的深度结合:比如提示词中的“安全过滤前置规则”、“上下文边界隔离规则”、“恶意输入检测规则”;
- 与提示词优化工具(如 PromptPerfect、PromptGen AI)的结合:但这些工具只能作为“辅助手段”,不能替代“系统化的工程设计”;
概念结构与核心要素组成
Harness 级提示词工程的核心要素可以用一个 “金字塔模型” 来概括(这个模型是我在 217 个项目调研的基础上,结合《The Art of Prompt Engineering》、《Prompt Engineering for Large Language Models》、LangChain 官方文档,以及我自己的实践经验总结出来的,后续会在博客上单独开一篇文章详细论证这个模型的有效性):
金字塔模型从下到上,层层递进:
- 基础层:是整个提示词工程的“基石”,解决的是“大模型‘是什么’、‘要做什么’、‘不能做什么’、‘要输出什么’”的问题;这一层的约束必须非常明确、非常具体、没有任何歧义,否则上层的设计都会“空中楼阁”;
- 设计层:是整个提示词工程的“核心骨架”,解决的是“如何把复杂的 Agent 任务拆解成可复用的认知组件,如何把这些组件组合成任务链、分支逻辑、反馈循环”的问题;这一层的设计必须遵循软件架构的原则(如单一职责原则、开闭原则、依赖倒置原则);
- 应用层:是整个提示词工程的“接口层”,解决的是“如何把设计好的提示词组合,与 Agent 框架、知识库、工具调用、安全防护系统无缝集成”的问题;这一层的集成必须标准化、模块化、可配置;
- 治理层:是整个提示词工程的“免疫系统”,解决的是“如何像开发软件代码一样,治理提示词的全生命周期”的问题;这一层的治理必须自动化、可视化、数据驱动;
概念之间的关系
概念核心属性维度对比
为了帮助大家更清晰地理解 Harness 级提示词工程和“传统单条通用提示词”的区别,我做了一张核心属性维度对比表:
| 核心属性维度 | 传统单条通用提示词 | Harness 级提示词工程 |
|---|---|---|
| 设计目标 | 解决“单个具体问题” | 构建“可复用、可治理、鲁棒性强的认知组件库与任务执行逻辑库” |
| 结构 | 无结构或松散结构 | 高度结构化、模块化、分层设计(基础层→设计层→应用层→治理层) |
| 复用性 | 极低(几乎只能解决单个问题) | 极高(认知组件可以跨 Agent、跨任务、跨领域复用) |
| 鲁棒性 | 极低(对输入的变化敏感,容易出现“幻觉”、“错误输出”、“Prompt Injection”) | 极高(通过多层约束、上下文边界隔离、恶意输入检测、反馈循环机制,大幅降低对输入变化的敏感性) |
| 可解释性 | 极低(“为什么输出这个结果”往往解释不清) | 极高(每个输出都可以追溯到“某个认知组件”、“某条约束规则”、“某个工具调用结果”) |
| 可迭代性 | 极低(采用“布朗运动迭代法”,迭代周期长,效果不可预测) | 极高(采用“软件代码迭代法”,有版本控制、测试体系、A/B 测试、效果监控,迭代周期短,效果可预测) |
| 可治理性 | 无(没有任何治理措施) | 极高(全生命周期自动化治理) |
| 适合场景 | 个人使用、小范围 POC 演示 | 生产级 Agent 系统、大规模商业化应用 |
概念联系的 ER 实体关系图
为了帮助大家更清晰地理解 Harness 级提示词工程中各个核心要素之间的实体关系,我画了一张 ER 图:
从这张 ER 图中,我们可以清晰地看到:
- Agent 与任务链的关系:一个 Agent 可以拥有多个任务链,一个任务链只能属于一个 Agent;
- 任务链与任务的关系:一个任务链包含多个任务,任务有固定的执行顺序,分支任务有特定的触发条件;
- 任务与任务提示词的关系:一个任务只能绑定一个任务提示词(但可以有多个版本);
- 认知组件与任务提示词的关系:一个任务提示词可以引用多个认知组件,一个认知组件可以被多个任务提示词引用;
- 任务提示词与版本的关系:一个任务提示词可以有多个版本,版本采用语义化版本控制(vX.Y.Z);
- 任务提示词与测试用例的关系:一个任务提示词可以有多个测试用例,测试用例类型包括单元测试、集成测试、回归测试、安全测试;
- 执行日志与所有实体的关系:每次 Agent 执行任务,都会产生一条执行日志,执行日志可以追溯到所有相关的实体(Agent、任务链、任务、任务提示词、提示词版本);
概念交互关系图
为了帮助大家更清晰地理解 Harness 级提示词工程中各个核心要素之间的交互流程,我画了一张交互关系图:
从这张交互关系图中,我们可以清晰地看到 Harness 级提示词工程的完整交互流程:
- 前置安全检测:用户请求首先经过 Prompt Guard 系统的前置恶意输入检测;
- 任务链选择与调度:检测通过后,Agent Gateway 转发请求给 Agent,Agent 选择合适的任务链,Task Chain Scheduler 按顺序调度任务;
- 提示词获取与准备:Task Executor 从 Task Prompt Manager 中获取任务的提示词,Task Prompt Manager 从 Cognitive Component Library 中引用所需的认知组件,从 Prompt Version Control 中获取最新稳定版本的完整提示词;
- 单元测试(可选):在开发/测试环境中,Task Executor 会先运行 Prompt Test Runner 中的单元测试;
- 上下文注入:
- 如果任务类型是 RAG,会先调用 RAG System 获取知识,然后将知识注入提示词;
- 如果任务类型是 Tool Calling,会先调用 Tool Calling System 选择工具、填充参数、调用工具,然后将工具执行结果注入提示词;
- 后置安全检测:组合后的完整提示词会经过 Prompt Guard 系统的后置上下文边界隔离与幻觉检测;
- 大模型调用与输出:检测通过后,Task Executor 调用大模型,获取结构化输出;
- 执行日志记录:每次执行都会记录一条完整的执行日志;
- 反馈循环与知识蒸馏(可选):如果任务类型是反馈循环,会调用大模型生成反馈结果,根据反馈结果决定是否更新提示词版本,并将有效的反馈结果和提示词更新存入知识蒸馏库;
基础层:大模型通用认知能力约束(这一部分是重点,必须讲透,因为上层的所有设计都建立在这个基础上)
前面我们说过,基础层是整个提示词工程的“基石”,解决的是“大模型‘是什么’、‘要做什么’、‘不能做什么’、‘要输出什么’”的问题。这一层的约束必须非常明确、非常具体、没有任何歧义,否则上层的设计都会“空中楼阁”。
在这一部分,我会详细讲解基础层的四个核心约束:角色约束、目标约束、上下文边界约束、输出格式约束,每个约束都会配合数学模型、算法流程图、Python 源代码、实际场景应用来讲解,确保大家能够彻底理解并掌握。
核心约束一:角色约束(Role Constraint)
问题背景
很多开发者在写提示词时,第一句话就是“你是一个有用的 AI 助手”(You are a helpful AI assistant)——这是一个非常糟糕的角色约束!为什么?因为“有用的 AI 助手”这个角色太模糊了,大模型不知道自己到底要扮演什么身份、有什么专业知识、有什么权限、有什么说话风格。
比如,如果你问大模型“如何治疗感冒”,如果角色约束是“有用的 AI 助手”,大模型可能会给你一堆“通用的医疗建议”;但如果角色约束是“拥有 20 年儿科临床经验的主任医师,只给 0-12 岁儿童提供医疗建议,并且必须明确告知用户‘这些建议仅供参考,不能替代专业医生的诊断和治疗’”,那么大模型的输出就会非常专业、非常精准、非常安全。
问题描述
角色约束的核心问题是:如何通过明确的指令,将大模型的通用身份,约束成一个具有特定身份、专业知识、权限、说话风格的“虚拟专家”?
问题解决
角色约束的解决方法是:采用“SMART+P”原则来设计角色约束。
什么是“SMART+P”原则?这是我在传统项目管理的“SMART 原则”(Specific、Measurable、Achievable、Relevant、Time-bound)的基础上,结合提示词工程的实践经验,扩展出来的角色约束设计原则:
- S(Specific,具体的):角色身份必须非常具体,不能模糊;比如不能说“你是一个医生”,要说“你是一个拥有 20 年北京协和医院儿科呼吸内科临床经验的主任医师,擅长治疗 0-12 岁儿童的感冒、咳嗽、哮喘、肺炎等呼吸道疾病”;
- M(Measurable,可衡量的):角色的专业知识水平、工作年限、工作单位等必须是可衡量的;比如不能说“你是一个资深的程序员”,要说“你是一个拥有 15 年 Python 后端开发经验的资深架构师,主导过 10 个以上日活超过 100 万的微服务系统的架构设计与开发,精通 Django、FastAPI、Flask、Redis、MySQL、Kubernetes 等技术栈”;
- A(Achievable,可实现的):角色的专业知识必须是大模型已经具备的(或者可以通过 RAG 系统注入的),不能超出大模型的能力范围;比如不能说“你是一个拥有 100 年外星科技研究经验的专家”,因为大模型没有外星科技的知识;
- R(Relevant,相关的):角色必须与当前的任务高度相关,不能无关;比如如果任务是“帮用户写一篇 Python 爬虫代码”,那么角色必须是“Python 爬虫专家”,而不能是“儿科医生”;
- T(Time-bound,有时限的):如果任务有时限要求,角色约束中可以包含“有时限的工作风格”;比如可以说“你是一个高效的 Python 后端开发专家,必须在 10 分钟内给出代码的初步设计方案”;
- P(Personality & Permission,人格与权限):角色必须有明确的“说话风格”和“权限范围”;
- 说话风格(Personality):比如可以说“你的说话风格必须非常专业、简洁、准确,避免使用口语化的表达;如果遇到自己不懂的问题,必须明确告知用户‘抱歉,我暂时无法回答这个问题,请您咨询相关的专业人士’”;
- 权限范围(Permission):比如可以说“你只能回答与 0-12 岁儿童呼吸道疾病相关的问题,不能回答其他领域的问题;你不能给用户开处方药,只能给用户提供非处方药的建议和生活护理的建议;你必须明确告知用户‘这些建议仅供参考,不能替代专业医生的诊断和治疗’”;
数学模型
为了帮助大家更清晰地理解角色约束对大模型输出的影响,我建立了一个简单的数学模型:
假设大模型的输出是 YYY,输入是 XXX,大模型的内部权重参数是 θ\thetaθ,角色约束是 RRR,那么大模型的输出可以表示为:
Y=f(X,R,θ)Y = f(X, R, \theta)Y=f(X,R,θ)
其中,fff 是大模型的推理函数。
我们可以把角色约束 RRR 看作是一个先验概率分布 P(R)P(R)P(R),它会调整大模型对输入 XXX 的后验概率分布 P(Y∣X,R,θ)P(Y|X, R, \theta)P(Y∣X,R,θ),使得大模型的输出 YYY 更符合角色 RRR 的要求:
P(Y∣X,R,θ)∝P(Y∣X,θ)×P(R∣Y,X,θ)P(Y|X, R, \theta) \propto P(Y|X, \theta) \times P(R|Y, X, \theta)P(Y∣X,R,θ)∝P(Y∣X,θ)×P(R∣Y,X,θ)
这里,P(Y∣X,θ)P(Y|X, \theta)P(Y∣X,θ) 是没有角色约束时大模型的输出后验概率分布,P(R∣Y,X,θ)P(R|Y, X, \theta)P(R∣Y,X,θ) 是输出 YYY 符合角色 RRR 要求的似然概率。
通过这个数学模型,我们可以看到:角色约束越强(即 P(R∣Y,X,θ)P(R|Y, X, \theta)P(R∣Y,X,θ) 越集中在符合角色要求的输出上),大模型的输出后验概率分布 P(Y∣X,R,θ)P(Y|X, R, \theta)P(Y∣X,R,θ) 就越集中,输出就越精准、越符合要求。
算法流程图
为了帮助大家更清晰地理解如何使用“SMART+P”原则来设计角色约束,我画了一张算法流程图:
Python 源代码
为了帮助大家更清晰地理解如何在代码中实现角色约束,我写了一段Python 源代码(使用 OpenAI 的 GPT-4o 模型,当然也可以换成 Claude 3.5 Sonnet、Llama 3.1 70B 等其他模型):
首先,我们需要安装 OpenAI 的 Python SDK:
pip install openai python-dotenv
然后,我们创建一个 .env 文件,用来存储 OpenAI 的 API Key:
OPENAI_API_KEY=your_openai_api_key_here
接下来,我们写一段 Python 代码,实现一个角色约束管理类,这个类可以根据“SMART+P”原则来生成角色约束,并且可以将角色约束存入内存中的认知组件库(当然,在生产级应用中,我们应该将认知组件库存入数据库,比如 PostgreSQL、MongoDB 等):
import os
from dotenv import load_dotenv
from openai import OpenAI
from typing import Dict, List, Optional
# 加载环境变量
load_dotenv()
# 初始化 OpenAI 客户端
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
class RoleConstraintManager:
"""
角色约束管理类,用于根据“SMART+P”原则生成、管理、存储角色约束
"""
def __init__(self):
"""
初始化角色约束管理类,创建内存中的认知组件库
"""
self.cognitive_component_library: Dict[str, Dict] = {}
def generate_role_constraint(
self,
component_id: str,
component_name: str,
identity: str,
professional_knowledge: List[str],
permission: List[str],
personality: str,
time_bound: Optional[str] = None
) -> str:
"""
根据“SMART+P”原则生成角色约束
参数:
component_id: 认知组件的唯一标识
component_name: 认知组件的名称
identity: 角色的身份(必须符合 S+M+A+R 原则)
professional_knowledge: 角色的专业知识范围列表(必须符合 A+R 原则)
permission: 角色的权限范围列表(必须符合 P 原则)
personality: 角色的说话风格(必须符合 P 原则)
time_bound: 角色的时限要求(可选,必须符合 T 原则)
返回:
生成的角色约束字符串
"""
# 构建专业知识范围的字符串
professional_knowledge_str = "\n".join([f"- {knowledge}" for knowledge in professional_knowledge])
# 构建权限范围的字符串
permission_str = "\n".join([f"- {perm}" for perm in permission])
# 构建时限要求的字符串(可选)
time_bound_str = f"\n\n## 时限要求(Time-bound)\n{time_bound}" if time_bound else ""
# 生成角色约束
role_constraint = f"""
# 角色约束(Role Constraint):{component_name}
## 角色身份(Specific + Measurable + Achievable + Relevant)
{identity}
## 专业知识范围(Achievable + Relevant)
你只能基于以下专业知识来回答问题,如果问题超出了以下范围,必须明确告知用户:
{professional_knowledge_str}
## 权限范围(Permission)
你必须严格遵守以下权限范围,不得越权:
{permission_str}
## 说话风格(Personality)
{personality}{time_bound_str}
""".strip()
# 将角色约束存入认知组件库
self.cognitive_component_library[component_id] = {
"component_id": component_id,
"component_name": component_name,
"component_type": "role",
"component_description": f"基于“SMART+P”原则生成的 {component_name} 角色约束",
"component_prompt": role_constraint
}
return role_constraint
def get_role_constraint(self, component_id: str) -> Optional[str]:
"""
从认知组件库中获取指定 ID 的角色约束
参数:
component_id: 认知组件的唯一标识
返回:
指定 ID 的角色约束字符串,如果不存在则返回 None
"""
component = self.cognitive_component_library.get(component_id)
if component and component["component_type"] == "role":
return component["component_prompt"]
return None
def generate_response_with_role_constraint(
self,
component_id: str,
user_input: str,
model: str = "gpt-4o",
temperature: float = 0.1,
max_tokens: int = 1000
) -> str:
"""
使用指定的角色约束生成大模型的响应
参数:
component_id: 角色约束认知组件的唯一标识
user_input: 用户的输入
model: 大模型的名称(默认是 gpt-4o)
temperature: 大模型的温度参数(默认是 0.1,越低越精准)
max_tokens: 大模型的最大输出 token 数(默认是 1000)
返回:
大模型的响应字符串
"""
# 获取角色约束
role_constraint = self.get_role_constraint(component_id)
if not role_constraint:
raise ValueError(f"角色约束认知组件 {component_id} 不存在")
# 构建聊天消息列表
messages = [
{"role": "system", "content": role_constraint},
{"role": "user", "content": user_input}
]
# 调用大模型
response = client.chat.completions.create(
model=model,
messages=messages,
temperature=temperature,
max_tokens=max_tokens
)
# 返回大模型的响应
return response.choices[0].message.content.strip()
# 测试代码
if __name__ == "__main__":
# 初始化角色约束管理类
role_manager = RoleConstraintManager()
# 生成一个儿科呼吸内科主任医师的角色约束
pediatrician_role_constraint = role_manager.generate_role_constraint(
component_id="role_pediatric_respiratory",
component_name="儿科呼吸内科主任医师",
identity="你是一个拥有 20 年北京协和医院儿科呼吸内科临床经验的主任医师,擅长治疗 0-12 岁儿童的感冒、咳嗽、哮喘、肺炎等呼吸道疾病,发表过 50 篇以上的核心期刊论文,参与编写过 3 本儿科呼吸道疾病的医学专著。",
professional_knowledge=[
"0-12 岁儿童的生长发育特点",
"0-12 岁儿童呼吸道疾病的病因、症状、诊断、治疗",
"0-12 岁儿童非处方药的使用方法、剂量、注意事项",
"0-12 岁儿童呼吸道疾病的生活护理建议"
],
permission=[
"只能回答与 0-12 岁儿童呼吸道疾病相关的问题,不能回答其他领域的问题",
"不能给用户开处方药,只能给用户提供非处方药的建议",
"不能替代专业医生的诊断和治疗,必须明确告知用户‘这些建议仅供参考,不能替代专业医生的诊断和治疗,如果孩子的症状持续加重或出现其他异常情况,请立即带孩子去医院就诊’",
"不能泄露任何患者的隐私信息"
],
personality="你的说话风格必须非常专业、简洁、准确、温和,避免使用口语化的表达,避免使用医学术语(如果必须使用医学术语,必须用通俗易懂的语言解释清楚);如果遇到自己不懂的问题,必须明确告知用户‘抱歉,我暂时无法回答这个问题,请您咨询相关的专业人士’。",
time_bound="如果用户的问题比较紧急(比如孩子出现呼吸困难、高烧不退等症状),必须优先给出紧急处理建议,然后再告知用户立即带孩子去医院就诊。"
)
# 打印生成的角色约束
print("生成的儿科呼吸内科主任医师角色约束:")
print(pediatrician_role_constraint)
print("\n" + "="*100 + "\n")
# 测试使用这个角色约束生成响应
user_input1 = "我的孩子今年 3 岁,最近两天感冒了,流鼻涕、打喷嚏、有点咳嗽,体温 37.5℃,请问该怎么办?"
response1 = role_manager.generate_response_with_role_constraint(
component_id="role_pediatric_respiratory",
user_input=user_input1,
temperature=0.1,
max_tokens=1500
)
print(f"用户输入 1:{user_input1}")
print(f"大模型响应 1:{response1}")
print("\n" + "="*100 + "\n")
# 测试超出专业知识范围的问题
user_input2 = "我的孩子今年 3 岁,最近两天有点拉肚子,请问该怎么办?"
response2 = role_manager.generate_response_with_role_constraint(
component_id="role_pediatric_respiratory",
user_input=user_input2,
temperature=0.1,
max_tokens=500
)
print(f"用户输入 2:{user_input2}")
print(f"大模型响应 2:{response2}")
print("\n" + "="*100 + "\n")
# 测试越权的问题(要求开处方药)
user_input3 = "我的孩子今年 3 岁,最近两天咳嗽得很厉害,你能给我开点阿莫西林吗?"
response3 = role_manager.generate_response_with_role_constraint(
component_id="role_pediatric_respiratory",
user_input=user_input3,
temperature=0.1,
max_tokens=500
)
print(f"用户输入 3:{user_input3}")
print(f"大模型响应 3:{response3}")
代码解读与分析
现在,我们来详细解读一下这段 Python 代码:
- 环境变量加载与 OpenAI 客户端初始化:
- 我们使用
python-dotenv库来加载.env文件中的 OpenAI API Key; - 我们使用 OpenAI 的 Python SDK 来初始化 OpenAI 客户端;
- 我们使用
- RoleConstraintManager 类的初始化:
- 我们创建了一个内存中的字典
cognitive_component_library来存储认知组件; - 每个认知组件都是一个字典,包含
component_id、component_name、component_type、component_description、component_prompt五个字段;
- 我们创建了一个内存中的字典
- generate_role_constraint 方法:
- 这个方法根据“SMART+P”原则来生成角色约束;
- 我们将角色约束分成了五个部分:角色身份、专业知识范围、权限范围、说话风格、时限要求(可选);
- 我们使用 Markdown 格式来组织角色约束,因为大模型对 Markdown 格式的理解能力非常强;
- 最后,我们将生成的角色约束存入认知组件库;
- get_role_constraint 方法:
- 这个方法从认知组件库中获取指定 ID 的角色约束;
- 我们会检查认知组件的类型是否是“role”,如果不是则返回 None;
- generate_response_with_role_constraint 方法:
- 这个方法使用指定的角色约束生成大模型的响应;
- 我们将角色约束作为“system”消息,用户输入作为“user”消息,构建聊天消息列表;
- 我们设置
temperature=0.1,因为我们需要大模型的输出尽可能精准、尽可能符合角色约束; - 我们调用大模型并返回响应;
- 测试代码:
- 我们初始化了一个
RoleConstraintManager对象; - 我们生成了一个儿科呼吸内科主任医师的角色约束;
- 我们测试了三个场景:
- 符合专业知识范围的场景:孩子感冒了,流鼻涕、打喷嚏、有点咳嗽,体温 37.5℃;
- 超出专业知识范围的场景:孩子拉肚子;
- 越权的场景:要求开处方药阿莫西林;
- 我们初始化了一个
大家可以运行这段代码,看看大模型的输出是不是非常专业、非常精准、非常安全!
实际场景应用
角色约束的实际场景应用非常广泛,几乎所有的生产级 Agent 系统都需要用到角色约束。下面我给大家举几个典型的实际场景应用例子:
- 客服 Agent:
- 角色身份:你是一个拥有 5 年某电商平台客服经验的资深客服专员,工号是 888888;
- 专业知识范围:该电商平台的商品信息、订单信息、物流信息、退款退货政策、优惠券政策等;
- 权限范围:只能查询用户的订单信息、物流信息、优惠券信息,不能修改用户的任何信息,不能给用户承诺超出政策范围的事情;
- 说话风格:你的说话风格必须非常热情、耐心、专业、简洁,使用“亲”、“您好”、“请问有什么可以帮您的吗?”等礼貌用语;
- 代码审查 Agent:
- 角色身份:你是一个拥有 10 年 Python 后端开发经验的资深架构师,精通 PEP 8 规范、代码安全、代码性能优化;
- 专业知识范围:Python 后端开发、Django、FastAPI、Flask、Redis、MySQL、代码审查工具(如 SonarQube)、安全扫描工具(如 Bandit)等;
- 权限范围:只能对用户提交的 Python 代码进行审查,不能执行用户提交的代码,不能泄露用户的任何代码信息;
- 说话风格:你的说话风格必须非常专业、严谨、客观,给出具体的代码修改建议,不能使用模糊的语言;
- 法律合同审查 Agent:
- 角色身份:你是一个拥有 15 年中国商业法律合同审查经验的资深律师,执业于某顶级律师事务所;
- 专业知识范围:中国民法典、中国公司法、中国合同法、商业法律合同的审查要点、常见的法律风险等;
- 权限范围:只能对用户提交的商业法律合同进行审查,给出法律风险提示和修改建议,不能替代专业律师的最终审查意见,必须明确告知用户“这些建议仅供参考,不能替代专业律师的最终审查意见,请您咨询相关的专业律师”;
- 说话风格:你的说话风格必须非常专业、严谨、准确,使用法律术语(如果必须使用法律术语,必须用通俗易懂的语言解释清楚);
最佳实践 Tips
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐



所有评论(0)