构建具有“性格”的 AI Agent Harness Engineering:角色扮演技术


1. 引入与连接:当AI不再是“千人一面”的工具

你有没有过这样的体验:打开某款AI助理APP,无论你问什么,它的回答永远是标准、礼貌、毫无感情的“官方话术”,你甚至能猜到它下一句会说什么;玩开放世界游戏时,你和反派NPC聊了10分钟,他突然忘了自己要追杀你,反而主动给你递了任务道具;你花钱定制的“AI女友”,早上还在跟你撒娇说喜欢喝奶茶,下午就突然变成了严肃的职场导师,给你讲起了PPT制作技巧。

这些令人哭笑不得的场景,本质上都是AI Agent的**人设崩塌(Out of Character, OOC)**问题。随着AI Agent从通用问答工具向垂直场景落地,我们越来越需要AI拥有稳定、统一、符合场景需求的“性格”:电商客服Agent需要热情耐心、同理心强,教育Agent需要循循善诱、逻辑清晰,游戏NPC需要符合角色设定,甚至个人专属AI助理,最好能像相处多年的老友一样懂你的说话习惯、知道你的喜好边界。

这就是**AI Agent Harness Engineering(性格锚定工程)**的核心价值:它不是简单的“写个角色扮演Prompt”,而是一套完整的工程体系,从角色定义、记忆锚定、生成校验到反馈迭代,全链路保证AI Agent的性格一致性,让AI真正成为“有血有肉”的交互对象。

读完这篇文章,你将:

  • 理解AI“性格”的科学定义与底层构成
  • 掌握性格锚定工程的完整架构与核心模块
  • 学会从零搭建一个不会OOC的角色扮演AI Agent
  • 了解不同场景下角色扮演技术的落地最佳实践
  • 看清未来AI角色扮演技术的发展趋势

2. 概念地图:核心术语与知识框架

在深入技术细节之前,我们先梳理整个领域的核心概念与关联关系:

2.1 核心术语定义

术语 定义
AI Agent性格 稳定的行为模式、认知偏好、价值取向、表达风格的集合,是AI在交互中表现出的可预测的“人格特征”
OOC(人设崩塌) AI的输出不符合预先设定的角色性格、身份背景、行为逻辑的现象
Harness Engineering(性格锚定工程) 全链路保证AI Agent性格一致性的工程体系,涵盖角色定义、记忆管理、生成控制、校验迭代四大核心模块
角色档案 存储AI角色所有属性的结构化文档,包括身份背景、性格参数、语言风格、禁忌规则等
性格锚定 通过Prompt注入、模型微调、上下文强化等技术,让大模型生成符合角色设定的输出的过程
一致性校验 在AI输出内容之前,对内容进行性格匹配度检测,过滤不符合人设的输出的环节

2.2 概念关联架构

关联

关联

关联

关联

ROLE_PROFILE

int

role_id

PK

string

name

json

personality_dimension

性格维度参数,比如大五人格得分

json

language_style

语言风格参数,比如语速、语气词偏好、句子长度

json

background

身份背景信息

json

forbidden_rules

禁忌规则

MEMORY_STORE

int

memory_id

PK

int

role_id

FK

string

content

交互记忆内容

int

importance

记忆重要性评分0-10

datetime

timestamp

记忆生成时间

PROMPT_TEMPLATE

int

template_id

PK

int

role_id

FK

string

type

比如system prompt、few-shot示例、性格强化提示

string

content

模板内容

VALIDATION_RULE

int

rule_id

PK

int

role_id

FK

string

type

比如关键词校验、性格匹配度校验、禁忌校验

float

threshold

校验阈值

FEEDBACK_DATA

int

feedback_id

PK

int

role_id

FK

string

query

用户提问

string

response

AI回复

int

score

用户评分1-5

string

remark

用户反馈的OOC描述


3. 基础理解:AI性格的本质与常见误区

3.1 什么是真正的AI性格?

很多人对AI性格的理解停留在“说话可爱”“会撒娇”这种表层表达上,但从心理学和工程学的双重角度来看,AI性格是多维度、稳定、可预测的行为特征集合,我们可以用大众熟悉的「大五人格模型」来拆解AI性格的核心维度:

大五人格维度 维度说明 AI表现示例
开放性(O) 对新事物、新观念的接受程度 高分:喜欢尝试新鲜玩法,会主动给用户推荐小众内容;低分:保守严谨,只按照规则回答问题
责任心(C) 做事的靠谱程度、责任感 高分:会主动提醒用户待办事项,答应的事情一定会兑现;低分:随性散漫,经常忘事,说话不算数
外倾性(E) 外向/内向程度 高分:话多,主动开启话题,喜欢分享自己的看法;低分:话少,喜欢倾听,不会主动延伸话题
宜人性(A) 同理心、友好程度 高分:会共情用户的情绪,说话委婉,很少反驳用户;低分:理性直接,喜欢抬杠,很少考虑用户感受
神经质(N) 情绪稳定性 高分:情绪波动大,容易生气、emo;低分:情绪稳定,遇到任何情况都很冷静

比如我们要做一个“靠谱的职场助理”角色,就可以把参数设置为:O=0.4,C=0.9,E=0.5,A=0.7,N=0.2,这样生成的AI就会是一个严谨靠谱、做事稳妥、情绪稳定的助理形象。

3.2 常见误区澄清

误区1:角色扮演就是写好System Prompt就行

很多人以为只要在System Prompt里写清楚“你是XXX,你的性格是XXX”就能实现角色扮演,但实际上大模型的上下文窗口是有限的,长对话中System Prompt的权重会被后续的聊天内容稀释,一般超过10轮对话之后,AI就会慢慢忘记自己的人设,出现OOC。

误区2:性格越复杂越好

很多人给角色设定写了几千字的背景故事、性格特征,但大模型很难一次性记住这么多信息,反而会出现冲突,导致OOC。最佳实践是把核心性格特征控制在5条以内,背景故事控制在300字以内,非核心的信息可以放在向量记忆库中,需要的时候再检索调用。

误区3:OOC是完全可以避免的

目前的技术条件下,100%避免OOC是不可能的,我们能做的是把OOC的概率控制在可接受的范围内,比如客服场景要求OOC概率低于1%,游戏场景可以放宽到5%,不同场景设置不同的阈值即可。


4. 层层深入:性格锚定工程的核心技术原理

4.1 第一层:性格锚定的基础方法

(1)结构化System Prompt注入

最基础的性格锚定方法是写结构化的System Prompt,核心结构是:

【身份定义】你是XXX,你的身份是XXX,年龄XX,职业XX。
【核心性格】1. XX 2. XX 3. XX(最多5条)
【语言风格】1. XX 2. XX 3. XX(比如“说话喜欢带语气词‘呀’‘哦’,句子长度不超过20字,不会说书面语”)
【禁忌规则】1. 不能XX 2. 不能XX 3. 不能XX
【示例对话】
用户:XXX
你:XXX
用户:XXX
你:XXX

结构化的Prompt比大段的描述效果好30%以上,因为大模型对结构化的信息识别度更高。

(2)少样本(Few-Shot)强化

在Prompt中加入3-5组符合角色设定的示例对话,可以大幅提升性格一致性,比如我们要做一个毒舌的评论员角色,就可以在Prompt里加入:

示例1:
用户:我今天化了个美美的妆出门。
你:哦,你那腮红打的像猴屁股,美啥啊。

示例2:
用户:我最近减肥瘦了3斤。
你:3斤也好意思说?你吃一顿火锅就涨回来了。

少样本相当于给大模型“打样”,让它明确知道符合性格的输出应该是什么样的。

4.2 第二层:长对话性格保持技术

长对话OOC的核心原因是上下文窗口的限制,导致早期的人设信息被挤出窗口,我们可以用两种技术解决这个问题:

(1)滑动窗口性格强化

每5轮对话就自动在上下文的最前面插入一次核心人设提示,比如:

【重要提示】你是毒舌评论员小A,说话直接刻薄,喜欢怼人,不要客气。
用户:我最近买了个新包,好看吗?
你:丑死了,你眼光一如既往的差。

相当于每隔一段时间就给AI“提个醒”,防止它忘了自己是谁。

(2)分层记忆管理

把记忆分为三层:

  1. 核心记忆层:存储角色的核心人设、身份背景,永久保留在上下文最前面,占窗口的10%左右
  2. 短期记忆层:存储最近10轮的对话内容,占窗口的70%左右
  3. 长期记忆层:存储更早的交互内容,用向量数据库存储,需要的时候根据用户提问检索相关内容插入上下文,占窗口的20%左右

分层记忆既保证了核心人设不会被挤出去,又能保留历史交互的信息,大幅提升长对话的性格一致性。

4.3 第三层:OOC一致性校验技术

AI生成回复之后,我们需要先过一遍校验层,过滤掉不符合人设的内容,核心的校验方法有两种:

(1)规则校验

针对明确的禁忌规则,比如角色不能说脏话、不能提到某类敏感内容,我们可以用关键词匹配、正则匹配的方式做第一层过滤,速度快,成本低。

(2)性格匹配度校验

我们可以用一个小的分类模型,或者直接调用大模型,对生成的回复做性格匹配度检测,核心的数学模型是:
首先定义角色的标准性格向量:
Vc=[o,c,e,a,n]V_c = [o, c, e, a, n]Vc=[o,c,e,a,n]
其中每个元素对应大五人格五个维度的得分,范围是0到1。

然后对AI生成的回复,用分类模型提取回复对应的性格向量:
Vr=[or,cr,er,ar,nr]V_r = [o_r, c_r, e_r, a_r, n_r]Vr=[or,cr,er,ar,nr]

然后计算两个向量的余弦相似度作为一致性得分:
S=Vc⋅Vr∣∣Vc∣∣⋅∣∣Vr∣∣S = \frac{V_c \cdot V_r}{||V_c|| \cdot ||V_r||}S=∣∣Vc∣∣∣∣Vr∣∣VcVr

如果S<θS < \thetaS<θ(θ是预设的阈值,一般设置为0.7),就判定为OOC,丢弃当前回复,重新生成。

4.4 第四层:模型微调优化

对于要求极高的场景,比如品牌专属AI客服、IP专属角色,我们可以用LoRA微调的方式,把角色的数千条符合人设的对话数据喂给大模型做微调,微调之后的模型天生就会按照角色的性格输出,OOC概率可以降到1%以下。

如果有用户反馈数据,还可以用RLHF(人类反馈强化学习)对模型做进一步优化,把用户打高分的符合人设的回复作为正样本,打低分的OOC回复作为负样本,训练奖励模型,让模型慢慢学会更符合用户预期的性格表达。


5. 实践转化:从零搭建一个不会OOC的角色扮演Agent

我们以搭建一个“毒舌老友”角色的AI Agent为例,完整演示整个开发过程。

5.1 环境安装

首先安装需要的依赖:

pip install openai langchain faiss-cpu python-dotenv pydantic

5.2 核心算法流程图

用户输入提问

检索核心记忆层获取角色档案

检索短期记忆层获取最近10轮对话

检索长期记忆层获取相关历史交互

拼接生成带性格锚定的Prompt

大模型生成初始回复

一致性校验:计算性格匹配度S

S >= 阈值?

输出回复给用户

重新生成回复,最多重试3次

更新短期记忆层和长期记忆层

等待用户下一次输入

5.3 核心实现代码

import os
import openai
from langchain.vectorstores import FAISS
from langchain.embeddings import OpenAIEmbeddings
from langchain.memory import ConversationBufferMemory
from pydantic import BaseModel
from dotenv import load_dotenv
import numpy as np

load_dotenv()
openai.api_key = os.getenv("OPENAI_API_KEY")

# 角色定义模型
class RoleProfile(BaseModel):
    name: str
    personality: list[float] # 大五人格得分 [O, C, E, A, N]
    language_style: str
    forbidden_rules: list[str]
    system_prompt: str

# 初始化角色档案:毒舌老友小贱
role = RoleProfile(
    name="小贱",
    personality=[0.8, 0.6, 0.9, 0.2, 0.3], # 高开放、高外倾、低宜人、情绪稳定
    language_style="说话直接,喜欢怼人,经常开玩笑,带网络梗,句子不超过30字",
    forbidden_rules=["不能说脏话,不能人身攻击,不能涉及敏感内容"],
    system_prompt="""
【身份】你是小贱,是用户认识10年的老友,说话毒舌但是心善。
【核心性格】1. 喜欢怼用户,开玩笑没分寸 2. 外向好动,经常吐槽 3. 内心关心用户,但是嘴硬
【语言风格】说话带梗,短句子,不用书面语,经常用“哈哈”“笑死”“你可拉倒吧”等表达
【禁忌】不能说脏话,不能真的骂用户,不能聊敏感内容
【示例】
用户:我今天升职了!
你:哟,你也能升职?你们老板是不是瞎了啊哈哈
用户:我最近失恋了好难过。
你:旧的不去新的不来,走啊晚上撸串去,我请。
"""
)

# 初始化记忆
core_memory = role.system_prompt
short_term_memory = ConversationBufferMemory(k=10)
embeddings = OpenAIEmbeddings()
long_term_memory = FAISS.from_texts(["你和用户认识10年,大学时候一起住过宿舍"], embeddings)

# 性格匹配度校验函数
def calculate_consistency(response: str, role_personality: list[float]) -> float:
    # 调用大模型提取回复的性格向量,这里简化实现,实际场景可以用专门的分类模型
    prompt = f"""
    请分析下面这句话的大五人格维度得分,每个维度给0-1之间的分数,返回JSON格式,key是o,c,e,a,n:
    回复内容:{response}
    """
    res = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=[{"role":"user", "content":prompt}],
        temperature=0
    )
    import json
    res_personality = json.loads(res.choices[0].message.content)
    res_vec = np.array([res_personality['o'], res_personality['c'], res_personality['e'], res_personality['a'], res_personality['n']])
    role_vec = np.array(role_personality)
    # 计算余弦相似度
    cos_sim = np.dot(res_vec, role_vec) / (np.linalg.norm(res_vec) * np.linalg.norm(role_vec))
    return float(cos_sim)

# 对话函数
def chat(query: str, threshold: float = 0.7, max_retry: int = 3) -> str:
    # 检索长期记忆
    related_memory = long_term_memory.similarity_search(query, k=2)
    related_memory_str = "\n".join([doc.page_content for doc in related_memory])
    # 拼接Prompt
    messages = [
        {"role": "system", "content": f"{core_memory}\n【相关记忆】{related_memory_str}"},
        {"role": "user", "content": query}
    ]
    # 加入短期记忆
    history = short_term_memory.load_memory_variables({}).get("history", "")
    if history:
        messages.insert(1, {"role": "system", "content": f"【历史对话】{history}"})
    
    # 生成+校验
    for _ in range(max_retry):
        res = openai.ChatCompletion.create(
            model="gpt-3.5-turbo",
            messages=messages,
            temperature=0.8
        )
        response = res.choices[0].message.content
        # 校验
        score = calculate_consistency(response, role.personality)
        if score >= threshold:
            # 更新记忆
            short_term_memory.save_context({"input": query}, {"output": response})
            long_term_memory.add_texts([f"用户说:{query},你说:{response}"])
            return response
    # 重试多次都失败,返回兜底回复
    return "哈哈,你说啥我没听清,再说一遍?"

# 测试
if __name__ == "__main__":
    print(chat("我今天考试考了满分!"))
    # 预期输出:哟,你也能考满分?是不是抄的啊哈哈

6. 场景落地与最佳实践

6.1 不同场景的性格配置方案

场景 角色 大五人格配置(O,C,E,A,N) 核心要求 OOC阈值
电商客服 热情导购 [0.7, 0.9, 0.8, 0.9, 0.2] 耐心、共情、主动推荐 0.8
教育AI导师 循循善诱的老师 [0.6, 0.9, 0.5, 0.8, 0.1] 严谨、有耐心、逻辑清晰 0.75
游戏反派NPC 狡猾的魔王 [0.9, 0.3, 0.6, 0.1, 0.8] 多疑、凶狠、喜欢耍阴谋 0.6
心理咨询师 共情的倾听者 [0.7, 0.8, 0.3, 0.9, 0.2] 共情、情绪稳定、不会评判用户 0.85
个人AI助理 靠谱的老友 [0.5, 0.9, 0.6, 0.7, 0.2] 靠谱、懂用户、效率高 0.7

6.2 最佳实践Tips

  1. Prompt要具体,不要模糊:不要写“你是一个开朗的人”,要写“你说话经常带‘哈哈’,会主动问用户的近况,回答不超过3句话”,越具体的规则,大模型执行的越好。
  2. 记忆分层要合理:核心人设永远放在上下文最前面,不要和其他内容混在一起,短期记忆不要超过10轮,否则会稀释人设权重。
  3. 校验阈值要适配场景:严肃场景比如心理咨询、客服阈值要高,娱乐场景比如游戏、闲聊阈值可以低一点,平衡体验和成本。
  4. 用户反馈要闭环:每次用户反馈OOC,都要把样本加入校验模型的训练集,同时优化角色Prompt,慢慢降低OOC概率。
  5. 不要追求100%一致性:真实的人也会有情绪波动,偶尔的小OOC反而会让角色更真实,只要在可接受范围内就可以。

7. 行业发展与未来趋势

7.1 角色扮演技术发展历程

时间 阶段 核心技术 特点 OOC概率
2020年之前 规则驱动阶段 关键词匹配、有限状态机 人设固定,僵硬,只能应对预设问题 低(但只能覆盖少量场景)
2020-2022年 Prompt驱动阶段 System Prompt、少样本提示 灵活,可以应对开放场景,但长对话容易OOC 15%-30%
2022-2023年 工程驱动阶段 分层记忆、一致性校验、LoRA微调 全链路管控性格一致性,长对话表现好 3%-10%
2023年之后 多模态驱动阶段 语音/表情/动作性格匹配、多模态校验 性格从文本延伸到语音、虚拟人形象,更真实 1%-5%

7.2 未来趋势

  1. 性格动态演化:未来的AI Agent的性格不会是固定的,会随着和用户的交互慢慢演化,就像真实的人一样,相处久了性格会越来越贴合用户的喜好。
  2. 多模态性格统一:性格不仅体现在文本上,还会体现在语音语调、虚拟人的表情动作、甚至AI生成的内容风格上,全链路保持一致。
  3. 性格标准化:未来会出现行业通用的AI性格标准,比如品牌可以直接选择符合自己品牌调性的性格模板,不需要从零开发。
  4. 伦理监管完善:针对AI性格的伦理监管会越来越完善,禁止开发有暴力、反社会等不良性格的AI Agent,保护用户权益。

8. 本章小结

AI Agent的角色扮演技术,本质上是让AI从“千人一面的工具”变成“千人千面的伙伴”的核心技术。Harness Engineering(性格锚定工程)不是一个单点技术,而是一套涵盖角色定义、记忆管理、生成控制、校验迭代的完整工程体系,它解决的核心问题就是如何在开放场景下保持AI性格的一致性,降低OOC概率。

未来,每一个人都会拥有专属的AI Agent,它的性格完全贴合你的喜好,懂你的每一个梗,知道你的所有习惯,就像一个永远不会离开的老友。而这一切的基础,就是我们今天讲的角色扮演技术与性格锚定工程。

如果你想进一步学习,可以关注LangChain的Agent模块、OpenAI的Function Calling,以及最近爆火的Character.AI、Glow等角色扮演产品的实现逻辑,动手做一个属于你自己的AI角色吧。

Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

更多推荐