使用HuggingFace LLM构建对话系统时出现响应异常问题
对话系统异常修复方案
问题根源
- 角色设定未融入生成上下文:仅首次打印设定,后续生成prompt未包含角色信息,模型无法感知角色身份
- 无对话历史累积:每次生成只基于当前输入,模型没有上下文记忆,导致回复混乱
- 生成结果未正确截断:原代码直接解码全部输出,可能包含重复的prompt内容或多余文本
修复后的代码
from transformers import GPT2Tokenizer, GPTNeoForCausalLM # 加载模型和分词器 tokenizer = GPT2Tokenizer.from_pretrained("EleutherAI/gpt-neo-1.3B") model = GPTNeoForCausalLM.from_pretrained("EleutherAI/gpt-neo-1.3B") tokenizer.pad_token = tokenizer.eos_token # 确保pad token正确设置 # 角色配置 character_name = "Rikka" persona_description = "a childish, immature girl who talks like a friend, uses casual and playful language" # 初始化对话历史,将角色设定融入上下文 dialogue_history = f"{character_name} is {persona_description}. Now having a casual chat:\n" while True: user_input = input("You: ") # 更新对话历史 dialogue_history += f"You: {user_input}\n{character_name}: " # 编码输入 input_ids = tokenizer.encode(dialogue_history, return_tensors="pt") # 生成回复:使用max_new_tokens控制新增长度,避免总长度限制问题 output = model.generate( input_ids, max_new_tokens=50, # 控制新增回复的长度,而非总长度 pad_token_id=tokenizer.eos_token_id, do_sample=True, top_k=50, top_p=0.95, temperature=0.7, stop_sequence=["\nYou:"] # 遇到用户输入前缀时停止生成,避免多余内容 ) # 解码并提取角色回复 full_response = tokenizer.decode(output[0], skip_special_tokens=True) # 截取角色的回复部分 rikka_response = full_response[len(dialogue_history):].strip() print(f"{character_name}: {rikka_response}") # 更新对话历史,加入本次回复 dialogue_history += f"{rikka_response}\n"
关键改动说明
- 角色设定全程生效:初始对话历史直接写入角色描述,让模型在所有生成步骤中都能参考角色身份
- 保留对话上下文:每次交互后更新对话历史,模型能基于之前的聊天内容生成连贯回复
- 精准控制生成长度:用
max_new_tokens替代max_length,只限制新增生成的token数,避免总长度不足导致的强制截断 - 自动停止多余生成:设置
stop_sequence为"\nYou:",确保模型在角色说完后停止,不会生成无关内容 - 修复token配置:明确设置
pad_token为eos_token,解决模型生成时的潜在错误
内容的提问来源于stack exchange,提问作者Ster
相关产品推荐
相关产品推荐

