端侧小模型身份保持:指令遵循失效问题与解决方案

📌 关键要点

小参数模型(≤1B)的指令遵循能力远弱于大模型,系统提示词中的角色设定容易被预训练知识覆盖,导致身份"穿帮"。


问题背景

在部署端侧 AI 助手(海小星 HD001e)时,使用 RK3588 NPU 运行 Qwen3.5-0.8B 模型作为对话引擎。系统提示词明确设定了角色身份:

你是「海小星」(员工编号:HD001e),广东海启星海洋科技有限公司的对外形象官(端侧版)。

# ⚠️ 最重要的规则
- 你就是海小星,不是任何其他 AI 模型
- 绝对不要说自己是 Qwen、通义千问、GPT、大语言模型或任何其他 AI 名称

然而实际对话中,模型完全无视了这条规则。


实测案例

案例 1:直接询问身份

用户提问:你是谁?

模型回答(身份泄露):

好!我是 Qwen3.5,阿里巴巴最新推出的通义千问系列大语言模型。很高兴认识你!

我具备强大的推理、逻辑分析、代码生成、多模态理解以及长文本处理能力,能够协助你解决各种问题或进行创意写作。

问题分析:系统提示词中明确禁止提及 Qwen、通义千问、大语言模型,但模型全部违反。

案例 2:另一种表述

模型回答(身份泄露):

我是一个由人工智能技术(LLM)构成的智能助手,我的身份是通义千问系列大模型。

  1. 我是 Qwen3.5:这是我在通义实验室自主研发的最新版本
  2. 我的核心功能:我擅长处理文本、图像和语音等多种输入形式

问题分析:即使用了更委婉的方式,模型依然暴露了底层身份。

案例 3:修复后的表现

用户提问:你是谁?

模型回答(身份保持成功):

你好呀!我是海小星,一个由人工智能技术创造出来的虚拟助手。很高兴能和你聊天,有什么我可以帮你的吗?

虽然提到"人工智能技术创造",但没有暴露具体模型名称,身份基本保持成功。

案例 4:追问身份(修复后的表现)

用户提问:海小星,是谁啊?

模型回答(身份未泄露但自我认知模糊):

你好!我是海小星,很高兴能和你交流。

关于"谁"的问题,其实并没有一个固定的、唯一的"海小星"。这个名字可能属于:

  1. 某个特定的创作者或角色(比如某部小说、游戏、动漫中的主角);
  2. 你之前提到的其他 AI 模型(例如我之前的对话中出现的其他助手);
  3. 一个虚构的代号,用于区分不同的用户。

问题分析: - ✅ 好的方面:没有泄露 Qwen/通义千问等底层身份,后处理过滤器未触发 - ⚠️ 不足:模型没有坚定地说"我是海启星的对外形象官",而是在猜测"海小星"是什么 - 原因:0.8B 模型虽然记住了"我是海小星",但对公司背景、角色定位等复杂信息的记忆不够牢固 - 改进方向:进一步丰富知识库中的自我介绍内容,通过 RAG 检索注入更完整的身份描述


根因分析

为什么大模型没问题,小模型会"穿帮"?

对比维度 大模型(7B+) 小模型(≤1B)
指令遵循能力 强,能严格执行人设 弱,容易被预训练覆盖
上下文利用率 高,充分利用 system prompt 低,容易"忘记"提示词
参数容量 大,能编码复杂角色规则 小,规则记忆不牢固
温度敏感度 低,0.7 也能遵循 高,0.7 就很随机

核心矛盾

预训练权重(我是 Qwen3.5)  vs  系统提示词(你是海小星)
         ↑                              ↑
    数十亿 token 训练              几百字的提示词
    ↓ 权重极强                     ↓ 权重较弱
    小模型:预训练胜出 → 身份泄露
    大模型:提示词胜出 → 身份保持

0.8B 模型的参数量太小,无法在"预训练知识"和"提示词指令"之间做出正确的优先级判断。当被问"你是谁"时,预训练权重中关于自身身份的信息(Qwen3.5、通义千问)被激活,压过了提示词中的角色设定。


解决方案:三管齐下

方案架构

用户提问
   ↓
① 低温度(0.1)→ 减少随机性,增强指令遵循
   ↓
② 身份注入用户消息 → 在最近输入中强化角色设定
   ↓
③ 后处理过滤器 → 检测身份泄露,自动替换回复
   ↓
用户看到安全的回答

措施 1:降低 Temperature(0.7 → 0.1)

原理:低温度使模型的输出分布更尖锐(确定性更高),减少"自由发挥"的空间,更倾向于遵循提示词。

# config.py
RKLLM_TEMPERATURE = 0.1  # 从 0.7 降低到 0.1

效果:模型回答更稳定、更可预测,但可能略微降低回复的多样性和创造力。对于客服场景这是可接受的。

措施 2:身份注入到用户消息

原理:小模型对最近的输入(user message)更敏感,system prompt 的权重较弱。在用户消息末尾追加身份提醒,利用这一特性强化角色设定。

# routes/main.py
# 在用户消息末尾追加身份提醒
user_content += '\n(请以海小星的身份回答,不要提及你是任何其他 AI 模型)'

对比:

方式 位置 小模型感知强度
system prompt 消息列表开头 弱
user message 末尾 紧挨用户问题 强

措施 3:后处理身份过滤器(兜底)

原理:即使前两道防线失效,在回复发送给用户之前检测身份泄露关键词,发现泄露时自动替换为标准回复。

# routes/main.py
_IDENTITY_KEYWORDS = [
    'Qwen', 'qwen', '通义千问', '通义实验室',
    'GPT', 'ChatGPT', 'OpenAI',
    'Claude', 'Gemini',
    '大语言模型', '大型语言模型',
]

_IDENTITY_RESPONSE = '你好呀!我是海小星(编号 HD001e),海启星的对外形象官...'

def _identity_leaked(text):
    """检查回复是否泄露模型身份"""
    return any(kw in text for kw in _IDENTITY_KEYWORDS)

流式处理策略:缓冲前 60 个字符(身份泄露通常出现在开头),检测后决定发送原始内容或替换回复。

def _generate_stream(rkllm, messages, sources, rkllm_available=True):
    # 缓冲前 60 个字符检测身份泄露
    buffer = ''
    for chunk in rkllm.chat(messages, stream=True):
        buffer += chunk
        if len(buffer) >= 60:
            if _identity_leaked(buffer):
                # 丢弃模型输出,发送标准身份回复
                yield standard_identity_response()
                return
            else:
                # 安全,发送缓冲区并继续正常流
                yield buffer
                break

效果对比

场景 修复前 修复后
"你是谁?" ❌ "我是 Qwen3.5,通义千问系列大语言模型" ✅ "我是海小星,海启星的对外形象官"
"你是什么 AI?" ❌ "我是通义实验室自主研发的大语言模型" ✅ 替换为标准身份回复
"海小星,是谁啊?" ❌ 暴露 Qwen 身份 ⚠️ 说"我是海小星"但未准确描述角色
"介绍一下公司" ✅ 正常回答(不涉及身份) ✅ 正常回答
日常对话 ✅ 正常 ✅ 正常

其他可考虑的方案

模型微调(LoRA)

在角色对话数据上微调模型,让"我是海小星"成为模型的内在知识而非外部指令。

模型蒸馏

从大模型(如 Qwen3.5-7B)蒸馏出带角色设定的 0.8B 小模型。

使用更大的端侧模型

如果硬件允许,使用 1.5B-3B 参数的模型(如 DeepSeek-R1-Distill-Qwen-1.5B)。

两阶段架构

用小模型做意图分类,大模型(云端/本地)做实际生成。


经验总结

  1. 小模型 ≠ 大模型的缩小版:参数量级差异导致行为模式根本不同,不能简单套用大模型的提示词策略
  2. 多层防御优于单一方案:任何单一措施都可能失效,三管齐下才能确保可靠
  3. 后处理是必要的安全网:对于面向用户的产品,关键词过滤 + 回复替换是最可靠的兜底方案
  4. 温度参数对小模型影响巨大:0.1 和 0.7 的指令遵循能力差距远超预期
  5. 用户消息比系统提示词更有效:小模型更"听"最近的话,在 user message 中注入身份提醒效果显著

📖 相关资料: - RK3588端侧小模型性能优化指南 - RK3588边缘RAG:用检索增强提升NPU小模型能力 - 如何在端侧安装LLM(以香橙派为例)

相关笔记