DeepSeek-R1-Distill-Qwen-1.5B实战教程:添加对话历史搜索功能支持关键词回溯
DeepSeek-R1-Distill-Qwen-1.5B实战教程:添加对话历史搜索功能支持关键词回溯
1. 项目概述
DeepSeek-R1-Distill-Qwen-1.5B是一个超轻量级的智能对话模型,专门为本地化部署设计。这个模型结合了DeepSeek优秀的逻辑推理能力和Qwen成熟的架构优势,经过蒸馏优化后,在保持强大性能的同时大幅降低了计算资源需求。
现在,我们要为这个已经很强大的对话助手添加一个实用功能:对话历史搜索。想象一下,当你和AI进行了长时间的对话后,想要找回之前讨论过的某个重要观点或代码示例,却需要手动翻阅所有聊天记录,这多么不方便。对话历史搜索功能就是为了解决这个问题而生的。
2. 为什么需要对话历史搜索
在实际使用中,我发现几个常见的痛点:
- 信息回溯困难:长时间的对话后,很难快速找到之前讨论过的特定内容
- 关键词记忆模糊:只记得大概的关键词,不记得具体在哪个对话中
- 效率低下:需要手动滚动查看所有历史消息,浪费时间和精力
添加搜索功能后,你可以:
- 输入关键词快速定位相关对话
- 查看包含关键词的所有历史消息
- 继续基于找到的历史内容进行深入讨论
3. 环境准备与快速部署
3.1 基础环境要求
确保你的环境满足以下要求:
# Python版本要求
Python 3.8+
# 主要依赖库
torch >= 2.0
transformers >= 4.30
streamlit >= 1.24
sentence-transformers >= 2.2
3.2 一键安装依赖
pip install torch transformers streamlit sentence-transformers
3.3 模型准备
如果你还没有下载模型,可以从魔塔平台获取:
# 模型下载(如果尚未下载)
# 通常模型会放置在 /root/ds_1.5b 目录
4. 实现对话历史搜索功能
4.1 搜索功能设计思路
我们要实现两种搜索方式:
- 关键词匹配搜索:基于文本内容直接匹配
- 语义相似度搜索:使用嵌入模型找到语义相关的内容
4.2 核心代码实现
首先,我们需要扩展对话历史管理功能:
import re
from sentence_transformers import SentenceTransformer
import numpy as np
class ChatHistoryManager:
def __init__(self):
self.history = []
self.embedding_model = None
self.history_embeddings = []
def initialize_embedding_model(self):
"""初始化语义搜索模型"""
try:
self.embedding_model = SentenceTransformer('all-MiniLM-L6-v2')
except:
print("语义搜索模型加载失败,将使用关键词搜索")
def add_to_history(self, role, content):
"""添加对话到历史记录"""
message = {
'role': role,
'content': content,
'timestamp': len(self.history)
}
self.history.append(message)
# 如果启用了语义搜索,同时生成嵌入
if self.embedding_model and content:
embedding = self.embedding_model.encode(content)
self.history_embeddings.append(embedding)
def keyword_search(self, query, max_results=5):
"""关键词搜索"""
results = []
query_lower = query.lower()
for i, message in enumerate(self.history):
if query_lower in message['content'].lower():
results.append({
'index': i,
'role': message['role'],
'content': message['content'],
'score': 1.0 # 关键词匹配得分为1
})
# 按时间倒序排列
results.sort(key=lambda x: x['index'], reverse=True)
return results[:max_results]
def semantic_search(self, query, max_results=5):
"""语义相似度搜索"""
if not self.embedding_model or not self.history_embeddings:
return self.keyword_search(query, max_results)
try:
# 生成查询嵌入
query_embedding = self.embedding_model.encode(query)
# 计算相似度
similarities = []
for i, emb in enumerate(self.history_embeddings):
similarity = np.dot(query_embedding, emb) / (
np.linalg.norm(query_embedding) * np.linalg.norm(emb)
)
similarities.append((i, similarity))
# 按相似度排序
similarities.sort(key=lambda x: x[1], reverse=True)
# 返回前N个结果
results = []
for idx, score in similarities[:max_results]:
message = self.history[idx]
results.append({
'index': idx,
'role': message['role'],
'content': message['content'],
'score': float(score)
})
return results
except Exception as e:
print(f"语义搜索出错: {e}")
return self.keyword_search(query, max_results)
4.3 集成到Streamlit界面
接下来,我们将搜索功能集成到现有的Streamlit界面中:
import streamlit as st
def setup_search_interface():
"""设置搜索界面"""
# 在侧边栏添加搜索功能
with st.sidebar:
st.header("🔍 对话历史搜索")
search_tab1, search_tab2 = st.tabs(["关键词搜索", "语义搜索"])
with search_tab1:
keyword_query = st.text_input("输入关键词", key="keyword_search")
if keyword_query:
results = st.session_state.history_manager.keyword_search(keyword_query)
display_search_results(results, "关键词")
with search_tab2:
semantic_query = st.text_input("输入搜索内容", key="semantic_search")
if semantic_query:
results = st.session_state.history_manager.semantic_search(semantic_query)
display_search_results(results, "语义")
def display_search_results(results, search_type):
"""显示搜索结果"""
if not results:
st.info("没有找到相关结果")
return
st.success(f"找到 {len(results)} 条{search_type}相关记录")
for result in results:
with st.expander(f"{result['role']}: {result['content'][:50]}..."):
st.write(f"**角色**: {result['role']}")
st.write(f"**相关度**: {result['score']:.3f}")
st.write(f"**内容**: {result['content']}")
# 添加继续对话按钮
if st.button("基于此继续对话", key=f"continue_{result['index']}"):
st.session_state.selected_context = result['content']
st.rerun()
4.4 完整集成示例
下面是完整的集成代码:
import streamlit as st
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch
from history_manager import ChatHistoryManager
# 初始化会话状态
if 'history_manager' not in st.session_state:
st.session_state.history_manager = ChatHistoryManager()
st.session_state.history_manager.initialize_embedding_model()
# 加载模型(使用缓存)
@st.cache_resource
def load_model():
tokenizer = AutoTokenizer.from_pretrained("/root/ds_1.5b", trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(
"/root/ds_1.5b",
device_map="auto",
torch_dtype="auto",
trust_remote_code=True
)
return tokenizer, model
def main():
st.title("DeepSeek-R1-Distill-Qwen-1.5B 智能对话")
# 加载模型
tokenizer, model = load_model()
# 设置搜索界面
setup_search_interface()
# 显示聊天历史
for message in st.session_state.history_manager.history:
with st.chat_message(message['role']):
st.markdown(message['content'])
# 聊天输入
if prompt := st.chat_input("考考 DeepSeek R1..."):
# 添加用户消息到历史
st.session_state.history_manager.add_to_history("user", prompt)
# 显示用户消息
with st.chat_message("user"):
st.markdown(prompt)
# 生成回复
with st.chat_message("assistant"):
with st.spinner("思考中..."):
# 准备输入
messages = [{"role": "user", "content": prompt}]
text = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
# 生成回复
with torch.no_grad():
inputs = tokenizer(text, return_tensors="pt").to(model.device)
outputs = model.generate(
**inputs,
max_new_tokens=2048,
temperature=0.6,
top_p=0.95,
do_sample=True
)
response = tokenizer.decode(
outputs[0][inputs.input_ids.shape[1]:],
skip_special_tokens=True
)
# 格式化输出
formatted_response = format_response(response)
st.markdown(formatted_response)
# 添加助手回复到历史
st.session_state.history_manager.add_to_history("assistant", formatted_response)
def format_response(response):
"""格式化模型输出"""
# 处理思考过程标签
response = response.replace("<|im_start|>", "").replace("<|im_end|>", "")
response = response.replace("reasoning", "思考过程").replace("answer", "回答")
return response
if __name__ == "__main__":
main()
5. 功能使用指南
5.1 基本搜索操作
- 打开搜索界面:在左侧侧边栏找到"对话历史搜索"板块
- 选择搜索方式:
- 关键词搜索:输入确切的关键词进行精确匹配
- 语义搜索:输入相关概念,找到语义相似的内容
- 查看结果:搜索结果会显示相关对话片段和相似度评分
- 继续对话:点击"基于此继续对话"可以从选中的历史内容继续讨论
5.2 搜索技巧
- 使用具体关键词:如"Python代码"、"数学题解"等
- 尝试同义词:如果找不到结果,尝试使用相近的词语
- 结合两种搜索:先用关键词搜索定位,再用语义搜索扩展
5.3 实际应用场景
# 示例对话历史:
# 用户:请帮我写一个Python函数计算斐波那契数列
# AI:提供了斐波那契数列的代码实现
# 用户:这个函数的时间复杂度是多少?
# 几天后,用户想要找回之前的代码:
# 在搜索框输入"斐波那契数列"
# 立即找到之前的对话和代码
# 可以基于此继续讨论优化方案
6. 性能优化建议
6.1 内存管理
对于大量对话历史,建议添加以下优化:
def optimize_memory_usage(self):
"""优化内存使用"""
# 定期清理旧的嵌入向量
if len(self.history_embeddings) > 1000: # 保留最近1000条
self.history_embeddings = self.history_embeddings[-1000:]
# 使用更轻量的模型
if self.embedding_model is None:
try:
self.embedding_model = SentenceTransformer('all-MiniLM-L6-v2')
except:
pass
6.2 搜索效率优化
def create_search_index(self):
"""创建搜索索引以提高效率"""
# 预处理文本内容
self.search_index = []
for message in self.history:
# 简单的文本预处理
processed = {
'content': message['content'].lower(),
'index': message['timestamp']
}
self.search_index.append(processed)
7. 常见问题解答
7.1 搜索功能相关问题
Q: 为什么有时候搜索不到结果? A: 可能是关键词不够准确,或者对话历史中没有相关内容。尝试使用更具体的关键词或语义搜索。
Q: 语义搜索和关键词搜索有什么区别? A: 关键词搜索需要精确匹配,语义搜索可以找到意思相近的内容,即使没有完全相同的词语。
Q: 搜索功能会影响对话性能吗? A: 基本不会。搜索操作只在用户主动搜索时进行,不会影响正常的对话流程。
7.2 技术实现问题
Q: 需要额外的模型下载吗? A: 语义搜索功能需要下载all-MiniLM-L6-v2模型(约90MB),但这是可选的。关键词搜索不需要额外下载。
Q: 如何扩展搜索功能? A: 你可以轻松添加新的搜索方式,比如按时间范围搜索、按角色过滤等。
8. 总结
通过为DeepSeek-R1-Distill-Qwen-1.5B添加对话历史搜索功能,我们大大提升了这个本地对话助手的实用性。现在你可以:
- 🔍 快速回溯:轻松找到之前的对话内容
- 💡 延续讨论:基于历史对话继续深入交流
- 🎯 精准定位:使用关键词或语义搜索精确找到需要的信息
- 💾 本地隐私:所有搜索都在本地完成,保障数据安全
这个功能的添加让长时间的AI对话变得更加高效和实用,特别适合需要频繁回溯之前讨论内容的用户。无论是技术讨论、学习交流还是创意发散,搜索功能都能帮你更好地管理和利用对话历史。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。
更多推荐

所有评论(0)