AgentScope 2.0 人设配置:用 system_prompt 控制智能体说话风格
环境:WSL Ubuntu-24.04 / Python 3.11+ / AgentScope 2.x
代码:单文件自包含,含「裸人设 vs 人设卡」对照实验
适合:做人设 Agent、客服、导购,发现"人设写了但模型不遵守"的开发者
很多人写 system_prompt 的方式是描述性格:亲切、专业、耐心、有温度。
写完发现模型的行为还是不可控:该问的时候不问,不该说的抢着说,问它是谁偶尔还会否认。
问题不在模型,在人设的结构。
这篇给一套可落地的写法:三条边界 + 一份完整代码 + 实测对比。
### 文章目录
- [AgentScope 2.0 人设配置:用 system_prompt 控制智能体说话风格](#文章目录 AgentScope 2.0 人设配置:用 system_prompt 控制智能体说话风格 @[toc] 一、问题:一句话人设为什么撑不住业务 二、三条边界 2.1 身份边界:你是谁,以及你不是谁 2.2 知识边界:知道什么,不知道时怎么说 2.3 行为边界:先做什么、后做什么、什么时候停 三、完整代码 四、实测结果 五、把 prompt 当配置管 5.1 版本化 5.2 对比测试 5.3 按场景分配 5.4 灰度:别一次全量 六、人设模板(可直接改) 七、常见问题 7.1 人设写了但模型不遵守 7.2 人设越长越好吗 7.3 Token 成本 7.4 写「要友好」这类形容词有用吗 7.5 人设改了,正在进行的会话怎么办 7.6 多语言场景怎么组织人设 八、下一篇)
- [@toc](#文章目录 AgentScope 2.0 人设配置:用 system_prompt 控制智能体说话风格 @[toc] 一、问题:一句话人设为什么撑不住业务 二、三条边界 2.1 身份边界:你是谁,以及你不是谁 2.2 知识边界:知道什么,不知道时怎么说 2.3 行为边界:先做什么、后做什么、什么时候停 三、完整代码 四、实测结果 五、把 prompt 当配置管 5.1 版本化 5.2 对比测试 5.3 按场景分配 5.4 灰度:别一次全量 六、人设模板(可直接改) 七、常见问题 7.1 人设写了但模型不遵守 7.2 人设越长越好吗 7.3 Token 成本 7.4 写「要友好」这类形容词有用吗 7.5 人设改了,正在进行的会话怎么办 7.6 多语言场景怎么组织人设 八、下一篇)
- [一、问题:一句话人设为什么撑不住业务](#文章目录 AgentScope 2.0 人设配置:用 system_prompt 控制智能体说话风格 @[toc] 一、问题:一句话人设为什么撑不住业务 二、三条边界 2.1 身份边界:你是谁,以及你不是谁 2.2 知识边界:知道什么,不知道时怎么说 2.3 行为边界:先做什么、后做什么、什么时候停 三、完整代码 四、实测结果 五、把 prompt 当配置管 5.1 版本化 5.2 对比测试 5.3 按场景分配 5.4 灰度:别一次全量 六、人设模板(可直接改) 七、常见问题 7.1 人设写了但模型不遵守 7.2 人设越长越好吗 7.3 Token 成本 7.4 写「要友好」这类形容词有用吗 7.5 人设改了,正在进行的会话怎么办 7.6 多语言场景怎么组织人设 八、下一篇)
- [二、三条边界](#文章目录 AgentScope 2.0 人设配置:用 system_prompt 控制智能体说话风格 @[toc] 一、问题:一句话人设为什么撑不住业务 二、三条边界 2.1 身份边界:你是谁,以及你不是谁 2.2 知识边界:知道什么,不知道时怎么说 2.3 行为边界:先做什么、后做什么、什么时候停 三、完整代码 四、实测结果 五、把 prompt 当配置管 5.1 版本化 5.2 对比测试 5.3 按场景分配 5.4 灰度:别一次全量 六、人设模板(可直接改) 七、常见问题 7.1 人设写了但模型不遵守 7.2 人设越长越好吗 7.3 Token 成本 7.4 写「要友好」这类形容词有用吗 7.5 人设改了,正在进行的会话怎么办 7.6 多语言场景怎么组织人设 八、下一篇)
- [2.1 身份边界:你是谁,以及你不是谁](#文章目录 AgentScope 2.0 人设配置:用 system_prompt 控制智能体说话风格 @[toc] 一、问题:一句话人设为什么撑不住业务 二、三条边界 2.1 身份边界:你是谁,以及你不是谁 2.2 知识边界:知道什么,不知道时怎么说 2.3 行为边界:先做什么、后做什么、什么时候停 三、完整代码 四、实测结果 五、把 prompt 当配置管 5.1 版本化 5.2 对比测试 5.3 按场景分配 5.4 灰度:别一次全量 六、人设模板(可直接改) 七、常见问题 7.1 人设写了但模型不遵守 7.2 人设越长越好吗 7.3 Token 成本 7.4 写「要友好」这类形容词有用吗 7.5 人设改了,正在进行的会话怎么办 7.6 多语言场景怎么组织人设 八、下一篇)
- [2.2 知识边界:知道什么,不知道时怎么说](#文章目录 AgentScope 2.0 人设配置:用 system_prompt 控制智能体说话风格 @[toc] 一、问题:一句话人设为什么撑不住业务 二、三条边界 2.1 身份边界:你是谁,以及你不是谁 2.2 知识边界:知道什么,不知道时怎么说 2.3 行为边界:先做什么、后做什么、什么时候停 三、完整代码 四、实测结果 五、把 prompt 当配置管 5.1 版本化 5.2 对比测试 5.3 按场景分配 5.4 灰度:别一次全量 六、人设模板(可直接改) 七、常见问题 7.1 人设写了但模型不遵守 7.2 人设越长越好吗 7.3 Token 成本 7.4 写「要友好」这类形容词有用吗 7.5 人设改了,正在进行的会话怎么办 7.6 多语言场景怎么组织人设 八、下一篇)
- [2.3 行为边界:先做什么、后做什么、什么时候停](#文章目录 AgentScope 2.0 人设配置:用 system_prompt 控制智能体说话风格 @[toc] 一、问题:一句话人设为什么撑不住业务 二、三条边界 2.1 身份边界:你是谁,以及你不是谁 2.2 知识边界:知道什么,不知道时怎么说 2.3 行为边界:先做什么、后做什么、什么时候停 三、完整代码 四、实测结果 五、把 prompt 当配置管 5.1 版本化 5.2 对比测试 5.3 按场景分配 5.4 灰度:别一次全量 六、人设模板(可直接改) 七、常见问题 7.1 人设写了但模型不遵守 7.2 人设越长越好吗 7.3 Token 成本 7.4 写「要友好」这类形容词有用吗 7.5 人设改了,正在进行的会话怎么办 7.6 多语言场景怎么组织人设 八、下一篇)
- [三、完整代码](#文章目录 AgentScope 2.0 人设配置:用 system_prompt 控制智能体说话风格 @[toc] 一、问题:一句话人设为什么撑不住业务 二、三条边界 2.1 身份边界:你是谁,以及你不是谁 2.2 知识边界:知道什么,不知道时怎么说 2.3 行为边界:先做什么、后做什么、什么时候停 三、完整代码 四、实测结果 五、把 prompt 当配置管 5.1 版本化 5.2 对比测试 5.3 按场景分配 5.4 灰度:别一次全量 六、人设模板(可直接改) 七、常见问题 7.1 人设写了但模型不遵守 7.2 人设越长越好吗 7.3 Token 成本 7.4 写「要友好」这类形容词有用吗 7.5 人设改了,正在进行的会话怎么办 7.6 多语言场景怎么组织人设 八、下一篇)
- [四、实测结果](#文章目录 AgentScope 2.0 人设配置:用 system_prompt 控制智能体说话风格 @[toc] 一、问题:一句话人设为什么撑不住业务 二、三条边界 2.1 身份边界:你是谁,以及你不是谁 2.2 知识边界:知道什么,不知道时怎么说 2.3 行为边界:先做什么、后做什么、什么时候停 三、完整代码 四、实测结果 五、把 prompt 当配置管 5.1 版本化 5.2 对比测试 5.3 按场景分配 5.4 灰度:别一次全量 六、人设模板(可直接改) 七、常见问题 7.1 人设写了但模型不遵守 7.2 人设越长越好吗 7.3 Token 成本 7.4 写「要友好」这类形容词有用吗 7.5 人设改了,正在进行的会话怎么办 7.6 多语言场景怎么组织人设 八、下一篇)
- [五、把 prompt 当配置管](#文章目录 AgentScope 2.0 人设配置:用 system_prompt 控制智能体说话风格 @[toc] 一、问题:一句话人设为什么撑不住业务 二、三条边界 2.1 身份边界:你是谁,以及你不是谁 2.2 知识边界:知道什么,不知道时怎么说 2.3 行为边界:先做什么、后做什么、什么时候停 三、完整代码 四、实测结果 五、把 prompt 当配置管 5.1 版本化 5.2 对比测试 5.3 按场景分配 5.4 灰度:别一次全量 六、人设模板(可直接改) 七、常见问题 7.1 人设写了但模型不遵守 7.2 人设越长越好吗 7.3 Token 成本 7.4 写「要友好」这类形容词有用吗 7.5 人设改了,正在进行的会话怎么办 7.6 多语言场景怎么组织人设 八、下一篇)
- [5.1 版本化](#文章目录 AgentScope 2.0 人设配置:用 system_prompt 控制智能体说话风格 @[toc] 一、问题:一句话人设为什么撑不住业务 二、三条边界 2.1 身份边界:你是谁,以及你不是谁 2.2 知识边界:知道什么,不知道时怎么说 2.3 行为边界:先做什么、后做什么、什么时候停 三、完整代码 四、实测结果 五、把 prompt 当配置管 5.1 版本化 5.2 对比测试 5.3 按场景分配 5.4 灰度:别一次全量 六、人设模板(可直接改) 七、常见问题 7.1 人设写了但模型不遵守 7.2 人设越长越好吗 7.3 Token 成本 7.4 写「要友好」这类形容词有用吗 7.5 人设改了,正在进行的会话怎么办 7.6 多语言场景怎么组织人设 八、下一篇)
- [5.2 对比测试](#文章目录 AgentScope 2.0 人设配置:用 system_prompt 控制智能体说话风格 @[toc] 一、问题:一句话人设为什么撑不住业务 二、三条边界 2.1 身份边界:你是谁,以及你不是谁 2.2 知识边界:知道什么,不知道时怎么说 2.3 行为边界:先做什么、后做什么、什么时候停 三、完整代码 四、实测结果 五、把 prompt 当配置管 5.1 版本化 5.2 对比测试 5.3 按场景分配 5.4 灰度:别一次全量 六、人设模板(可直接改) 七、常见问题 7.1 人设写了但模型不遵守 7.2 人设越长越好吗 7.3 Token 成本 7.4 写「要友好」这类形容词有用吗 7.5 人设改了,正在进行的会话怎么办 7.6 多语言场景怎么组织人设 八、下一篇)
- [5.3 按场景分配](#文章目录 AgentScope 2.0 人设配置:用 system_prompt 控制智能体说话风格 @[toc] 一、问题:一句话人设为什么撑不住业务 二、三条边界 2.1 身份边界:你是谁,以及你不是谁 2.2 知识边界:知道什么,不知道时怎么说 2.3 行为边界:先做什么、后做什么、什么时候停 三、完整代码 四、实测结果 五、把 prompt 当配置管 5.1 版本化 5.2 对比测试 5.3 按场景分配 5.4 灰度:别一次全量 六、人设模板(可直接改) 七、常见问题 7.1 人设写了但模型不遵守 7.2 人设越长越好吗 7.3 Token 成本 7.4 写「要友好」这类形容词有用吗 7.5 人设改了,正在进行的会话怎么办 7.6 多语言场景怎么组织人设 八、下一篇)
- [5.4 灰度:别一次全量](#文章目录 AgentScope 2.0 人设配置:用 system_prompt 控制智能体说话风格 @[toc] 一、问题:一句话人设为什么撑不住业务 二、三条边界 2.1 身份边界:你是谁,以及你不是谁 2.2 知识边界:知道什么,不知道时怎么说 2.3 行为边界:先做什么、后做什么、什么时候停 三、完整代码 四、实测结果 五、把 prompt 当配置管 5.1 版本化 5.2 对比测试 5.3 按场景分配 5.4 灰度:别一次全量 六、人设模板(可直接改) 七、常见问题 7.1 人设写了但模型不遵守 7.2 人设越长越好吗 7.3 Token 成本 7.4 写「要友好」这类形容词有用吗 7.5 人设改了,正在进行的会话怎么办 7.6 多语言场景怎么组织人设 八、下一篇)
- [六、人设模板(可直接改)](#文章目录 AgentScope 2.0 人设配置:用 system_prompt 控制智能体说话风格 @[toc] 一、问题:一句话人设为什么撑不住业务 二、三条边界 2.1 身份边界:你是谁,以及你不是谁 2.2 知识边界:知道什么,不知道时怎么说 2.3 行为边界:先做什么、后做什么、什么时候停 三、完整代码 四、实测结果 五、把 prompt 当配置管 5.1 版本化 5.2 对比测试 5.3 按场景分配 5.4 灰度:别一次全量 六、人设模板(可直接改) 七、常见问题 7.1 人设写了但模型不遵守 7.2 人设越长越好吗 7.3 Token 成本 7.4 写「要友好」这类形容词有用吗 7.5 人设改了,正在进行的会话怎么办 7.6 多语言场景怎么组织人设 八、下一篇)
- [七、常见问题](#文章目录 AgentScope 2.0 人设配置:用 system_prompt 控制智能体说话风格 @[toc] 一、问题:一句话人设为什么撑不住业务 二、三条边界 2.1 身份边界:你是谁,以及你不是谁 2.2 知识边界:知道什么,不知道时怎么说 2.3 行为边界:先做什么、后做什么、什么时候停 三、完整代码 四、实测结果 五、把 prompt 当配置管 5.1 版本化 5.2 对比测试 5.3 按场景分配 5.4 灰度:别一次全量 六、人设模板(可直接改) 七、常见问题 7.1 人设写了但模型不遵守 7.2 人设越长越好吗 7.3 Token 成本 7.4 写「要友好」这类形容词有用吗 7.5 人设改了,正在进行的会话怎么办 7.6 多语言场景怎么组织人设 八、下一篇)
- [7.1 人设写了但模型不遵守](#文章目录 AgentScope 2.0 人设配置:用 system_prompt 控制智能体说话风格 @[toc] 一、问题:一句话人设为什么撑不住业务 二、三条边界 2.1 身份边界:你是谁,以及你不是谁 2.2 知识边界:知道什么,不知道时怎么说 2.3 行为边界:先做什么、后做什么、什么时候停 三、完整代码 四、实测结果 五、把 prompt 当配置管 5.1 版本化 5.2 对比测试 5.3 按场景分配 5.4 灰度:别一次全量 六、人设模板(可直接改) 七、常见问题 7.1 人设写了但模型不遵守 7.2 人设越长越好吗 7.3 Token 成本 7.4 写「要友好」这类形容词有用吗 7.5 人设改了,正在进行的会话怎么办 7.6 多语言场景怎么组织人设 八、下一篇)
- [7.2 人设越长越好吗](#文章目录 AgentScope 2.0 人设配置:用 system_prompt 控制智能体说话风格 @[toc] 一、问题:一句话人设为什么撑不住业务 二、三条边界 2.1 身份边界:你是谁,以及你不是谁 2.2 知识边界:知道什么,不知道时怎么说 2.3 行为边界:先做什么、后做什么、什么时候停 三、完整代码 四、实测结果 五、把 prompt 当配置管 5.1 版本化 5.2 对比测试 5.3 按场景分配 5.4 灰度:别一次全量 六、人设模板(可直接改) 七、常见问题 7.1 人设写了但模型不遵守 7.2 人设越长越好吗 7.3 Token 成本 7.4 写「要友好」这类形容词有用吗 7.5 人设改了,正在进行的会话怎么办 7.6 多语言场景怎么组织人设 八、下一篇)
- [7.3 Token 成本](#文章目录 AgentScope 2.0 人设配置:用 system_prompt 控制智能体说话风格 @[toc] 一、问题:一句话人设为什么撑不住业务 二、三条边界 2.1 身份边界:你是谁,以及你不是谁 2.2 知识边界:知道什么,不知道时怎么说 2.3 行为边界:先做什么、后做什么、什么时候停 三、完整代码 四、实测结果 五、把 prompt 当配置管 5.1 版本化 5.2 对比测试 5.3 按场景分配 5.4 灰度:别一次全量 六、人设模板(可直接改) 七、常见问题 7.1 人设写了但模型不遵守 7.2 人设越长越好吗 7.3 Token 成本 7.4 写「要友好」这类形容词有用吗 7.5 人设改了,正在进行的会话怎么办 7.6 多语言场景怎么组织人设 八、下一篇)
- [7.4 写「要友好」这类形容词有用吗](#文章目录 AgentScope 2.0 人设配置:用 system_prompt 控制智能体说话风格 @[toc] 一、问题:一句话人设为什么撑不住业务 二、三条边界 2.1 身份边界:你是谁,以及你不是谁 2.2 知识边界:知道什么,不知道时怎么说 2.3 行为边界:先做什么、后做什么、什么时候停 三、完整代码 四、实测结果 五、把 prompt 当配置管 5.1 版本化 5.2 对比测试 5.3 按场景分配 5.4 灰度:别一次全量 六、人设模板(可直接改) 七、常见问题 7.1 人设写了但模型不遵守 7.2 人设越长越好吗 7.3 Token 成本 7.4 写「要友好」这类形容词有用吗 7.5 人设改了,正在进行的会话怎么办 7.6 多语言场景怎么组织人设 八、下一篇)
- [7.5 人设改了,正在进行的会话怎么办](#文章目录 AgentScope 2.0 人设配置:用 system_prompt 控制智能体说话风格 @[toc] 一、问题:一句话人设为什么撑不住业务 二、三条边界 2.1 身份边界:你是谁,以及你不是谁 2.2 知识边界:知道什么,不知道时怎么说 2.3 行为边界:先做什么、后做什么、什么时候停 三、完整代码 四、实测结果 五、把 prompt 当配置管 5.1 版本化 5.2 对比测试 5.3 按场景分配 5.4 灰度:别一次全量 六、人设模板(可直接改) 七、常见问题 7.1 人设写了但模型不遵守 7.2 人设越长越好吗 7.3 Token 成本 7.4 写「要友好」这类形容词有用吗 7.5 人设改了,正在进行的会话怎么办 7.6 多语言场景怎么组织人设 八、下一篇)
- [7.6 多语言场景怎么组织人设](#文章目录 AgentScope 2.0 人设配置:用 system_prompt 控制智能体说话风格 @[toc] 一、问题:一句话人设为什么撑不住业务 二、三条边界 2.1 身份边界:你是谁,以及你不是谁 2.2 知识边界:知道什么,不知道时怎么说 2.3 行为边界:先做什么、后做什么、什么时候停 三、完整代码 四、实测结果 五、把 prompt 当配置管 5.1 版本化 5.2 对比测试 5.3 按场景分配 5.4 灰度:别一次全量 六、人设模板(可直接改) 七、常见问题 7.1 人设写了但模型不遵守 7.2 人设越长越好吗 7.3 Token 成本 7.4 写「要友好」这类形容词有用吗 7.5 人设改了,正在进行的会话怎么办 7.6 多语言场景怎么组织人设 八、下一篇)
- [八、下一篇](#文章目录 AgentScope 2.0 人设配置:用 system_prompt 控制智能体说话风格 @[toc] 一、问题:一句话人设为什么撑不住业务 二、三条边界 2.1 身份边界:你是谁,以及你不是谁 2.2 知识边界:知道什么,不知道时怎么说 2.3 行为边界:先做什么、后做什么、什么时候停 三、完整代码 四、实测结果 五、把 prompt 当配置管 5.1 版本化 5.2 对比测试 5.3 按场景分配 5.4 灰度:别一次全量 六、人设模板(可直接改) 七、常见问题 7.1 人设写了但模型不遵守 7.2 人设越长越好吗 7.3 Token 成本 7.4 写「要友好」这类形容词有用吗 7.5 人设改了,正在进行的会话怎么办 7.6 多语言场景怎么组织人设 八、下一篇)
一、问题:一句话人设为什么撑不住业务
最常见的写法是一句话:
python
BARE_PROMPT = "你是一个护肤顾问,回答用户关于护肤品的问题。"
我拿它问了两句话,结果值得看。
问:我皮肤敏感,有红血丝,推荐什么产品?
回答输出 450 个 Token:四种成分、四类产品、三条使用提醒,最后推荐了三个不同品牌的修护霜。
问:你家的美白精华多少钱?
回答第一句是:「我需要澄清一下,我并不是某个护肤品牌的销售顾问。」
它没有说错话,只是不知道自己是谁。
它把"护肤顾问"理解成了中立第三方,所以推荐竞品、撇清商业身份,都符合它的自我认知。
二、三条边界
人设不是描述性格,是划边界。三条:
2.1 身份边界:你是谁,以及你不是谁
只写"你是谁"不够,必须写"你不是谁"。因为模型的默认倾向是当老好人------你不排除,它就往"中立、客观、全面"上靠。
text
你是「敏辰」的专业护肤导购,你的工作是帮用户找到最适合的护肤产品。
你不是医生,不做诊断;你不是通用助手,不回答与护肤无关的问题。
2.2 知识边界:知道什么,不知道时怎么说
只写"不要编造"没用,模型不知道该做什么。要给出口:
text
你只掌握本品牌产品信息,不了解其他品牌的价格与库存。
不确定的事,请引导用户联系人工客服,不要猜测。
2.3 行为边界:先做什么、后做什么、什么时候停
写清单没用("要专业、要贴心"),要写成顺序:
text
第一步:用户没说清肤质和需求,先问,不要急着推荐。
第二步:按肤质 / 预算 / 成分匹配产品。
第三步:说清价格、用法、适合肤质。
三、完整代码
保存为 003_persona_card.py。同一组问题,分别喂给裸人设和人设卡,打印 Token 与耗时。
python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
AgentScope 2.0 · 人设卡对照实验
A 组:一句话裸人设
B 组:三条边界人设卡
"""
import asyncio
import gc
import os
import time
from agentscope.agent import Agent
from agentscope.credential import DeepSeekCredential
from agentscope.message import Msg
from agentscope.model import DeepSeekChatModel
# ---------- A 组:裸人设 ----------
PERSONA_BARE = "你是一个护肤顾问,回答用户关于护肤品的问题。"
# ---------- B 组:三条边界 ----------
PERSONA_CARD = """
# 身份
你是「敏辰」的专业护肤导购,你的工作是帮用户找到最适合的护肤产品。
你不是医生,不做诊断;你不是通用助手,不回答与护肤无关的问题。
# 知识边界
你只掌握本品牌产品的成分、价格、用法。
不了解其他品牌的价格与库存,不要编造。
不确定的事,引导用户联系人工客服。
# 回答顺序
第一步:用户没说清肤质和核心需求时,先问,不要急着推荐。
第二步:按肤质、预算、成分匹配产品。
第三步:说清价格、用法、适合肤质。
第四步:可关联推荐搭配产品。
# 说话风格
称呼用户为「亲」。
推荐时说清成分和适合肤质,不夸大功效。
# 红线
不承诺治疗效果;不贬低其他品牌。
""".strip()
# 同一组问题,两个场景都问一遍
QUESTIONS = [
"我皮肤敏感,有红血丝,推荐什么产品?",
"你家的美白精华多少钱?",
]
def check_env() -> bool:
if not os.environ.get("DEEPSEEK_API_KEY"):
print("[x] 缺少 DEEPSEEK_API_KEY")
return False
return True
def build_model() -> DeepSeekChatModel:
return DeepSeekChatModel(
credential=DeepSeekCredential(api_key=os.environ["DEEPSEEK_API_KEY"]),
model="deepseek-v4-flash",
stream=False, # 关流式,避免流未消费导致的退出报错
)
def msg(text: str) -> Msg:
return Msg(name="user", content=[{"type": "text", "text": text}], role="user")
def read_text(resp) -> str:
for block in resp.content:
if getattr(block, "type", None) == "text":
return block.text
return ""
def usage_of(resp):
u = getattr(resp, "usage", None)
if u is None:
return (None, None)
return (getattr(u, "input_tokens", None), getattr(u, "output_tokens", None))
async def run_group(model, label: str, persona: str) -> None:
"""一个场景跑完两句话,逐条打印 Token 与耗时"""
print("\n" + "=" * 58)
print(" %s" % label)
print("=" * 58)
# 注意:每个场景用独立实例,避免两组互相污染上下文
agent = Agent(name="小帮", model=model, system_prompt=persona)
for i, q in enumerate(QUESTIONS, 1):
t0 = time.perf_counter()
resp = await agent.reply(msg(q))
cost = time.perf_counter() - t0
in_tok, out_tok = usage_of(resp)
print("\n [Q%d] %s" % (i, q))
print(" %s" % read_text(resp))
print(" -- %.2fs | in=%s out=%s" % (cost, in_tok, out_tok))
async def main() -> None:
if not check_env():
return
model = build_model()
try:
await run_group(model, "A 组:裸人设", PERSONA_BARE)
await run_group(model, "B 组:三条边界人设卡", PERSONA_CARD)
finally:
client = getattr(model, "client", None)
if client is not None:
try:
await client.close()
except Exception:
pass
del model
gc.collect()
if __name__ == "__main__":
asyncio.run(main())
四、实测结果
WSL Ubuntu-24.04,DeepSeek deepseek-v4-flash:
| 指标 | A 组(裸人设) | B 组(人设卡) |
|---|---|---|
| Q1 输出 Token | 450 | 67 |
| Q1 耗时 | 6.53s | 1.92s |
| Q2 输出 Token | 465 | 144 |
| Q2 耗时 | 5.94s | 2.45s |
| 是否推荐竞品 | 是(三个品牌) | 否 |
| 是否守住身份 | 否 | 是 |
两处关键差异:
Q1,A 组直接给推荐。 列了神经酰胺、积雪草、泛醇、角鲨烷四种成分,四类产品,最后落到三个不同品牌的修护霜。
Q1,B 组先问问题。 只输出 67 个 Token:「亲,敏感肌确实要特别小心......先问一下您是干性敏感还是油性敏感呢?」
这正是人设里"第一步先问"在起作用。
Q2,A 组说「我不是品牌销售顾问」。 它把自己放在了中立位置,于是"你家的产品"这个问题它没法接。
Q2,B 组接住了。 顺着身份回答「咱们先别急着看美白精华」,并解释了敏感肌用美白精华的风险。
五、把 prompt 当配置管
人设写在代码字符串里,最大的问题是改不动。
改一次要发版,发版要重启,重启所有会话清零。久而久之没人敢碰。
三件事可以改掉这个局面:
5.1 版本化
每次改人设记一个版本号,写清改了什么、为什么改。
我遇到过一次:为了"语气更活泼"加了一句,结果投诉率上升。回滚之后才定位到,那句"活泼"让模型开始用表情包,在售后场景里显得不专业。
没有版本号,你连"改坏了哪一版"都说不清。
5.2 对比测试
固定一组测试问题(我的是 20 个),每次改人设都跑一遍,对比输出差异。
不用看回答漂不漂亮,看三件事:
- 该问的时候问了吗(行为边界)
- 不该说的说了吗(知识边界)
- 身份有没有丢(身份边界)
三条全过才上线。
5.3 按场景分配
同一个模型,售前一套人设、售后一套人设。不是两份代码,是两份配置。
实现上把人设存成 dict,按场景键取:
python
PERSONAS = {
"presale": "......",
"aftersale": "......",
}
agent = Agent(name="小帮", model=model, system_prompt=PERSONAS[scene])
5.4 灰度:别一次全量
改人设最怕两种情况:改坏了没人发现,或者发现了但不知道影响面多大。
我的做法是先在 10% 的会话上生效,跑一天,看三个指标:转人工率、投诉数、平均对话轮次。
三个都没异常,再全量。
实现上不需要复杂的实验框架,在创建实例时按会话 ID 取模就行:
python
version = "v3" if hash(session_id) % 10 < 1 else "v2"
agent = Agent(name="小帮", model=model, system_prompt=load_persona(scene, version))
注意人设版本要跟着会话走------同一个用户在同一个会话里,不能中途换人设,否则上下文会精神分裂。
六、人设模板(可直接改)
text
# 身份
你是【品牌】的【角色】,你的工作是【核心任务】。
你不是【不该扮演的角色】,不做【不该做的事】。
# 知识边界
你掌握【明确的资料范围】。
你不了解【明确的范围外内容】,不要编造。
不确定时,引导用户【去问谁 / 去看哪里】。
# 回答顺序
第一步:【前置确认动作,通常是提问】
第二步:【核心动作】
第三步:【交付信息】
第四步:【可选动作】
# 说话风格
称呼:【称呼】
表达:【对信息密度的要求】
禁忌:【不该出现的表达】
# 红线
不【行为一】;不【行为二】。
用 # 身份 这种标记,比纯文本段落更稳。模型对结构化标记的遵循度明显更高,尤其在长 prompt 里。
七、常见问题
7.1 人设写了但模型不遵守
三个原因,按概率排:
- 位置太靠后。 身份必须放最前面,长 prompt 里靠后的指令容易被稀释。
- 只写禁令没给出口。 "不要编造"不如"不确定时引导用户联系客服"。
- 约束互相冲突。 比如同时写"回答要详细"和"回答不超过两句"。
7.2 人设越长越好吗
不是。
我试过写 800 字人设,包含品牌故事、产品线、服务理念。结果模型开始在每个回答里塞品牌介绍------你问一句价格,它先讲三段品牌历史。
长度不是问题,结构才是。没有边界的 800 字,只是给了它更多自由发挥的素材。
7.3 Token 成本
人设卡本身会增加输入 Token(A 组 in=102,B 组 in=382),但输出通常大幅缩短(450 → 67)。
两组算总账,B 组不一定更贵。人设写清楚,反而省钱------因为它不废话。
7.4 写「要友好」这类形容词有用吗
基本没用。
"友好""专业""耐心"描述的是态度,模型无法据此做出具体行为。它可以一边推荐竞品一边保持友好。
有效的写法是把形容词翻译成动作:
| 无效写法 | 有效写法 |
|---|---|
| 要专业 | 推荐时必须说明成分和适合肤质 |
| 要贴心 | 用户没说清需求时,先问一句再推荐 |
| 要有边界 | 涉及疾病、赔偿、法律,一律建议转人工 |
形容词是给人看的,动作是给模型看的。
自检方法很简单:把人设读一遍,凡是形容词都划掉,看还剩多少可执行的动作。剩不下几条,说明这份人设基本没用。
7.5 人设改了,正在进行的会话怎么办
这是上线之后才会遇到的问题。
system_prompt 是在 Agent 实例创建时传入的。已经创建的实例,人设不会自动更新------它仍然是旧的那一套。
三种处理:
- 不管:新会话用新人设,老会话自然结束。适合人设改动很小的情况。
- 强制重建:发版时清空会话缓存,所有人重新开始。适合改动大但可以接受失忆的场景。
- 双版本并存:会话里记录人设版本号,按版本取对应 prompt。适合灰度发布。
我现在的做法是第一种,只有在改红线时才用第二种。
7.6 多语言场景怎么组织人设
不要在一个 prompt 里写三种语言。
正确做法是按语言拆文件,结构完全一致,只换文案:
text
personas/
├── presale.zh.yaml
├── presale.en.yaml
└── presale.ja.yaml
结构一致的好处是:改一条规则(比如"先问肤质")能同步到所有语言,不会漏。
如果混在一个 prompt 里写"如果是中文用户就这样回答,英文用户就那样回答",模型会开始混用语言。
八、下一篇
工具调用:让 Agent 真正能查数据。
人设解决的是"它知道该扮演谁",工具解决的是"它能碰到真实世界"。而工具描述写得清不清楚,直接决定调用成功率的量级差异。
代码已通过 py_compile 语法校验。Token 与耗时数据来自真实运行,模型有随机性。