最近在项目里用Claude Code系统提示词,踩了不少坑。一开始觉得提示词不就是写几句话让AI理解意图嘛,真用起来才发现,在复杂业务场景下,问题一个接一个冒出来。今天就把这段时间的实战经验整理一下,希望能帮到正在入门的同学。

图片

1. 背景痛点:那些让人头疼的典型问题

刚开始接入Claude Code时,我们遇到了几个非常典型的问题,直接影响了线上效果。

1.1 意图识别偏差 这是最常见的问题。比如我们有个客服场景,用户说“帮我查下订单”,AI可能理解成查询所有订单,但用户实际想查的是“最新未发货的订单”。在简单场景下,提示词还能应付,一旦业务逻辑复杂,AI就容易“跑偏”。我们发现,当用户query包含多个意图或存在歧义时,Claude Code很容易选择概率最高的那个解释,而不是最符合业务逻辑的那个。

1.2 多轮对话断层 对话进行到第三轮、第四轮时,AI经常“失忆”。比如:

  • 用户:我想订一张明天去北京的机票
  • AI:好的,请问您需要什么时间段的?
  • 用户:下午的
  • AI:请问您的出发地是哪里?

看到没?AI已经忘了用户要去的是“北京”。虽然Claude Code有上下文窗口,但如果不做特殊处理,重要的对话信息很容易在几轮之后被稀释或遗忘。

1.3 长文本处理缺陷 当我们需要处理长文档(比如一篇技术文章或一份产品说明书)时,Claude Code对超出token限制的部分会进行截断。更麻烦的是,它可能只记住了开头和结尾,中间的关键信息被忽略了。我们做过测试,让AI总结一篇5000字的文档,如果不用分块处理,关键信息的召回率不到60%。

2. 技术对比:三种提示词方案怎么选?

为了解决这些问题,我们尝试了三种不同的提示词方案,下面是我们的对比测试结果:

方案类型 核心思路 TPS(请求/秒) 准确率 维护成本 适用场景
规则模板 预定义模板+变量填充 1200+ 85%-90% 流程固定、意图明确的场景
动态生成 实时生成提示词 300-500 92%-95% 需求多变、个性化强的场景
混合模式 模板为主,动态补充 800-1000 90%-93% 中高 大多数业务场景

规则模板的优势是速度快、稳定,但灵活性差。每次业务变更都要改模板,维护起来很痛苦。

动态生成的准确率最高,因为提示词是根据当前对话状态实时生成的,但计算开销大,TPS上不去。

混合模式是我们最终选择的方案:用模板保证基础框架,在关键位置动态插入上下文信息。这样既保持了性能,又有了足够的灵活性。

3. 核心实现:构建带上下文记忆的提示词引擎

下面是我们实际在用的Python实现,重点解决了上下文记忆和意图fallback的问题。

import json
from collections import OrderedDict
from typing import Dict, List, Optional, Any
import hashlib
import re


class ClaudePromptEngine:
    """
    Claude Code提示词引擎
    实现基于LRU的对话缓存和意图分类fallback机制
    """
    
    def __init__(self, max_cache_size: int = 100, max_context_turns: int = 10):
        """
        初始化提示词引擎
        
        Args:
            max_cache_size: LRU缓存的最大容量
            max_context_turns: 最大对话轮次
        """
        self.max_cache_size = max_cache_size
        self.max_context_turns = max_context_turns
        
        # 使用OrderedDict实现LRU缓存
        self.conversation_cache = OrderedDict()
        
        # 意图分类器(简化版,实际项目中可用BERT等模型)
        self.intent_patterns = {
            'query_order': [r'查.*订单', r'订单.*状态', r'我的订单'],
            'modify_order': [r'改.*订单', r'修改.*信息', r'变更'],
            'cancel_order': [r'取消.*订单', r'不要了', r'退订']
        }
        
        # 系统提示词模板
        self.system_template = """你是一个专业的客服助手。请根据对话历史回答用户问题。
        
对话历史:{history}

当前用户输入:{query}

请按照以下格式回复:
1. 识别用户意图:{intent}
2. 提取关键信息:{entities}
3. 生成回复内容:{response}

如果无法确定意图,请询问用户澄清。"""
    
    def _get_cache_key(self, user_id: str, session_id: str) -> str:
        """
        生成缓存键
        
        Args:
            user_id: 用户ID
            session_id: 会话ID
            
        Returns:
            缓存键字符串
        """
        key_str = f"{user_id}_{session_id}"
        return hashlib.md5(key_str.encode()).hexdigest()
    
    def _update_cache(self, key: str, conversation: List[Dict]) -> None:
        """
        更新LRU缓存
        
        Args:
            key: 缓存键
            conversation: 对话历史
        """
        if key in self.conversation_cache:
            # 移动到最新位置
            self.conversation_cache.move_to_end(key)
        else:
            # 新增记录
            self.conversation_cache[key] = conversation
            
            # 如果超过最大容量,移除最旧的记录
            if len(self.conversation_cache) > self.max_cache_size:
                self.conversation_cache.popitem(last=False)
    
    def _classify_intent(self, query: str) -> str:
        """
        意图分类,包含fallback机制
        
        Args:
            query: 用户查询
            
        Returns:
            识别到的意图,如果无法识别则返回'unknown'
        """
        query_lower = query.lower()
        
        # 第一层:模式匹配
        for intent, patterns in self.intent_patterns.items():
            for pattern in patterns:
                if re.search(pattern, query_lower):
                    return intent
        
        # 第二层:关键词匹配(fallback)
        keyword_mapping = {
            'query_order': ['订单', '查', '状态', '物流'],
            'modify_order': ['改', '修改', '变更', '更新'],
            'cancel_order': ['取消', '退', '不要', '删除']
        }
        
        for intent, keywords in keyword_mapping.items():
            for keyword in keywords:
                if keyword in query_lower:
                    return intent
        
        # 第三层:默认返回unknown
        return 'unknown'
    
    def _extract_entities(self, query: str, intent: str) -> Dict[str, Any]:
        """
        从查询中提取实体信息
        
        Args:
            query: 用户查询
            intent: 识别到的意图
            
        Returns:
            提取的实体字典
        """
        entities = {}
        
        # 提取订单号(示例)
        order_pattern = r'订单[号|码]?[::]?\s*(\w{8,12})'
        order_match = re.search(order_pattern, query)
        if order_match:
            entities['order_id'] = order_match.group(1)
        
        # 提取时间信息
        time_pattern = r'(\d{1,2}月\d{1,2}日|\d{4}[-/]\d{1,2}[-/]\d{1,2}|明天|今天|后天)'
        time_match = re.search(time_pattern, query)
        if time_match:
            entities['time'] = time_match.group(1)
        
        return entities
    
    def generate_prompt(self, user_id: str, session_id: str, query: str) -> Dict[str, Any]:
        """
        生成完整的提示词
        
        Args:
            user_id: 用户ID
            session_id: 会话ID
            query: 用户当前查询
            
        Returns:
            包含提示词和元数据的字典
        """
        # 获取缓存键
        cache_key = self._get_cache_key(user_id, session_id)
        
        # 获取对话历史
        conversation = self.conversation_cache.get(cache_key, [])
        
        # 限制历史记录长度
        if len(conversation) > self.max_context_turns * 2:  # 每轮包含用户和AI两条记录
            conversation = conversation[-(self.max_context_turns * 2):]
        
        # 构建历史记录字符串
        history_str = ""
        for i in range(0, len(conversation), 2):
            if i + 1 < len(conversation):
                history_str += f"用户:{conversation[i]}\n"
                history_str += f"助手:{conversation[i+1]}\n"
        
        # 意图分类
        intent = self._classify_intent(query)
        
        # 实体提取
        entities = self._extract_entities(query, intent)
        
        # 生成最终提示词
        prompt = self.system_template.format(
            history=history_str if history_str else "无",
            query=query,
            intent=intent,
            entities=json.dumps(entities, ensure_ascii=False),
            response=""
        )
        
        # 更新对话历史
        conversation.append(query)
        self._update_cache(cache_key, conversation)
        
        return {
            'prompt': prompt,
            'intent': intent,
            'entities': entities,
            'history_length': len(conversation)
        }
    
    def add_response_to_history(self, user_id: str, session_id: str, response: str) -> None:
        """
        将AI回复添加到对话历史
        
        Args:
            user_id: 用户ID
            session_id: 会话ID
            response: AI回复内容
        """
        cache_key = self._get_cache_key(user_id, session_id)
        
        if cache_key in self.conversation_cache:
            self.conversation_cache[cache_key].append(response)
            # 更新缓存位置
            self.conversation_cache.move_to_end(cache_key)


# 使用示例
if __name__ == "__main__":
    # 初始化引擎
    engine = ClaudePromptEngine(max_cache_size=50, max_context_turns=5)
    
    # 模拟对话
    test_cases = [
        ("user123", "session456", "帮我查一下订单号:ORD202312345678"),
        ("user123", "session456", "这个订单什么时候能发货?"),
        ("user123", "session456", "我想修改收货地址")
    ]
    
    for user_id, session_id, query in test_cases:
        result = engine.generate_prompt(user_id, session_id, query)
        print(f"查询:{query}")
        print(f"识别意图:{result['intent']}")
        print(f"提取实体:{result['entities']}")
        print("-" * 50)
        
        # 模拟AI回复
        engine.add_response_to_history(user_id, session_id, "这是模拟回复")

这个引擎的核心设计思路是:

  1. LRU缓存管理对话历史:避免内存无限增长,同时保持最近对话的活跃度
  2. 三层意图识别fallback:从精确匹配到模糊匹配,确保总能给出一个意图分类
  3. 模板与动态结合:系统提示词框架固定,但历史记录和实体信息动态填充

4. 生产考量:性能优化与安全防护

4.1 并发场景下的token消耗优化

在生产环境中,token消耗直接关系到成本。我们总结了几条优化经验:

分块处理长文本

def chunk_text(text: str, max_tokens: int = 2000) -> List[str]:
    """
    将长文本分块,确保每块不超过最大token数
    
    Args:
        text: 输入文本
        max_tokens: 每块最大token数(按字符数简单估算)
        
    Returns:
        文本块列表
    """
    # 简单按段落分割(实际可按句子、固定长度等更精细分割)
    paragraphs = text.split('\n\n')
    chunks = []
    current_chunk = []
    current_length = 0
    
    for para in paragraphs:
        para_length = len(para)
        
        if current_length + para_length > max_tokens and current_chunk:
            # 保存当前块
            chunks.append('\n\n'.join(current_chunk))
            current_chunk = [para]
            current_length = para_length
        else:
            current_chunk.append(para)
            current_length += para_length
    
    if current_chunk:
        chunks.append('\n\n'.join(current_chunk))
    
    return chunks

缓存重复计算 对于相同的查询,我们可以缓存AI的回复。特别是那些频繁出现的通用问题,缓存命中率能达到30%以上。

精简提示词 定期review提示词,删除冗余内容。我们通过A/B测试发现,精简后的提示词在效果不变的情况下,能减少15%-20%的token消耗。

4.2 Prompt注入防御方案

Prompt注入是安全方面的大问题。用户可能通过精心构造的输入,让AI执行非预期的操作。

基础防御:输入过滤

def sanitize_input(user_input: str) -> str:
    """
    清理用户输入,防止prompt注入
    
    Args:
        user_input: 用户输入
        
    Returns:
        清理后的安全文本
    """
    # 移除可能用于注入的特殊指令
    injection_patterns = [
        r'(?i)ignore.*previous.*instruction',  # 忽略之前的指令
        r'(?i)system.*prompt',  # 系统提示词
        r'(?i)role.*play',  # 角色扮演
        r'(?i)act.*as',  # 扮演...
        r'(?i)you.*are.*now',  # 你现在是...
        r'```.*```',  # 代码块
        r'"""',  # 多行字符串
    ]
    
    cleaned_input = user_input
    for pattern in injection_patterns:
        cleaned_input = re.sub(pattern, '[FILTERED]', cleaned_input)
    
    # 限制输入长度
    if len(cleaned_input) > 1000:
        cleaned_input = cleaned_input[:1000] + '...'
    
    return cleaned_input

进阶防御:输出验证

def validate_output(ai_output: str, expected_intent: str) -> bool:
    """
    验证AI输出是否符合预期
    
    Args:
        ai_output: AI生成的输出
        expected_intent: 预期意图
        
    Returns:
        是否通过验证
    """
    # 检查是否包含危险操作
    dangerous_actions = [
        '删除所有', '格式化', '关机', '重启',
        '修改密码', '提升权限', '执行代码'
    ]
    
    for action in dangerous_actions:
        if action.lower() in ai_output.lower():
            return False
    
    # 检查是否符合预期意图
    if expected_intent == 'query_order':
        # 查询订单的回复应该包含订单信息
        if not any(keyword in ai_output for keyword in ['订单', '编号', '状态']):
            return False
    
    return True

系统层防御

  • 使用单独的模型处理用户输入和系统指令
  • 实现多轮对话的完整性检查
  • 记录所有异常输出,用于后续分析

5. 避坑指南:三个真实故障分析

案例一:特殊字符导致的解析异常

问题描述:用户输入中包含Markdown格式的代码块,导致AI的回复格式混乱。

根本原因:用户输入了这样的内容:

请帮我检查这段代码:
```python
print("Hello, World!")

有什么问题吗?

我们的系统没有对Markdown标记进行转义,AI在回复时也使用了代码块,导致前端显示异常。

**解决方案**:
```python
def escape_markdown(text: str) -> str:
    """转义Markdown特殊字符"""
    # 需要转义的字符
    escape_chars = ['`', '*', '_', '{', '}', '[', ']', '(', ')', '#', '+', '-', '.', '!']
    
    for char in escape_chars:
        text = text.replace(char, f'\\{char}')
    
    return text

案例二:上下文窗口溢出导致信息丢失

问题描述:在长达20轮的对话后,AI开始忘记早期的关键信息。

根本原因:我们只是简单地将所有历史对话拼接起来,没有做重要性筛选。当对话轮次增多时,早期的重要信息被“挤”出了上下文窗口。

解决方案:实现重要性加权机制

def summarize_conversation(conversation: List[Dict]) -> str:
    """
    对话摘要,保留重要信息
    
    Args:
        conversation: 完整对话历史
        
    Returns:
        摘要后的对话历史
    """
    # 给不同类型的对话内容赋予不同权重
    weight_map = {
        'user_intent': 3.0,  # 用户意图声明
        'ai_confirmation': 2.0,  # AI确认信息
        'user_detail': 1.5,  # 用户提供详细信息
        'ai_question': 1.0,  # AI提问
        'small_talk': 0.5,  # 闲聊内容
    }
    
    # 根据权重筛选重要对话
    important_turns = []
    for turn in conversation[-10:]:  # 最近10轮必保留
        important_turns.append(turn)
    
    # 从更早的对话中选取高权重的
    for turn in conversation[:-10]:
        if turn.get('weight', 1.0) >= 1.5:
            important_turns.append(turn)
    
    return important_turns

案例三:温度参数设置不当导致输出不稳定

问题描述:同样的输入,AI的回复时好时坏,有时很准确,有时完全跑偏。

根本原因:temperature参数设置过高(0.9),导致AI的创造性太强,在需要准确性的业务场景中不稳定。

解决方案:动态调整temperature

def get_temperature(intent: str, query_complexity: float) -> float:
    """
    根据意图和查询复杂度动态调整temperature
    
    Args:
        intent: 用户意图
        query_complexity: 查询复杂度评分(0-1)
        
    Returns:
        合适的temperature值
    """
    base_temps = {
        'query_order': 0.1,  # 查询类需要高确定性
        'modify_order': 0.3,  # 修改类中等确定性
        'creative_writing': 0.7,  # 创作类需要多样性
        'unknown': 0.5,  # 未知意图使用默认值
    }
    
    base_temp = base_temps.get(intent, 0.5)
    
    # 查询越复杂,temperature越低(越需要确定性)
    adjusted_temp = base_temp * (1.0 - query_complexity * 0.5)
    
    # 确保在合理范围内
    return max(0.1, min(0.9, adjusted_temp))

图片

写在最后

经过几个月的实践,我们总结出Claude Code提示词系统的几个关键点:

  1. 不要追求完美的一次性设计:提示词系统需要持续迭代,根据实际使用数据不断优化
  2. 监控比想象中更重要:不仅要监控准确率,还要监控token消耗、响应时间、异常请求等
  3. 安全防护不能事后补:从一开始就要考虑prompt注入、数据泄露等安全问题

最后留两个问题给大家思考:

  1. 在多租户的SaaS系统中,如何设计提示词系统才能平衡个性化与系统性能?每个租户可能有不同的业务需求,但为每个租户单独维护一套提示词成本太高。

  2. 当业务逻辑非常复杂,需要AI进行多步骤推理时,如何设计提示词才能保证推理过程的可靠性和可解释性?特别是当某一步推理出错时,如何让AI能够“回退”到上一步重新思考?

这些问题没有标准答案,需要根据具体业务场景来探索。希望我们的经验能给你一些启发,也欢迎分享你的实践心得。

Logo

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

更多推荐