DeepSeek-R1聊天机器人开发教程
AI 领域的进步速度确实在以前所未有的速度前进。短短一周多的时间,DeepSeek-R1 LLM 模型的发布就以其令人印象深刻的准确性震撼了 AI 世界,其准确性与现有模型相当,但创建成本仅为典型成本的一小部分。
DeepSeek 团队成功地将其庞大的 671B 参数模型的推理能力提炼为基于 Qwen(DeepSeek-R1-Distill-Qwen-1.5B、7B、14B 和 32B)和 Llama(DeepSeek-R1-Distill-Llama-8B 和 70B)的 6 个小模型。这实际上意味着你可以使用自己的模型副本 - 自定义它、进行更改、在本地运行它或将其托管在云平台上。
在本博客中,我们用 Python 构建一个 DeepSeek-R1 聊天机器人。简而言之,Streamlit 用于前端,而在后端,通过对托管在 Snowflake 中的 DeepSeek-R1 模型的 API 调用,可以实现为应用程序的响应提供支持的 LLM 模型。
点击这里查看本教程的 GitHub 存储库。
1、什么是 DeepSeek-R1?
简而言之,DeepSeek-R1 是一种推理模型,它利用强化学习来教授基本语言模型 DeepSeek-V3 进行推理,而无需人工监督。
以下是 DeepSeek-R1 的 5 个主要功能:
- 最先进的推理:DeepSeek-R1 在高级数学任务上可以达到 97.3% 的准确率,优于早期的基准。同样,它在 AIME 2024 上的得分为 79.8%,在 SWE-bench Verified 上的得分为 49.2%,也优于其他模型。
- 成本效率:与行业标准相比,DeepSeek 模型的训练成本显著降低
- 应用广泛:在创意写作、长上下文理解和事实问答方面表现出色。
- 可扩展性:模型有多个精简版本(1.5B 到 70B 个参数),从而优化了能力和资源使用之间的平衡。
- 可访问性:开源可用性使开发人员和研究人员能够尝试该模型,以将高级 AI 工具应用于实际项目。
尽管其性能出色,但人们仍可能对其使用方面的安全问题感到担忧。鉴于此,由于模型是开源的,因此可以检查底层代码,而模型本身可以在用户自己的计算资源上自行部署。
在本教程中,我们将使用托管在 Snowflake 平台中的 DeepSeek-R1 模型。
2、应用程序概述
以下是 DeepSeek-R1 聊天机器人应用程序的高级概述:
- 用户提供提示输入(即提出问题)。
- 通过使用
SNOWFLAKE.CORTEX.COMPLETE()
进行 LLM 调用,其中提交提示输入,并获取 LLM 生成的响应,并将其显示在应用程序中。
3、聊天机器人的运行
让我们看看聊天机器人的实际运行,启动聊天机器人并在聊天输入中输入问题:
作为推理模型,LLM 首先进入思考阶段:
思考过程完成后,最终答案将在下面显示:
应该注意的是,思考和答案的深度直接受到最大令牌参数的影响。在这里,我们将最大令牌限制为 800 个以进行测试,但你可以将其增加到 20,480。
4、构建 DeepSeek-R1 聊天机器人
现在让我们继续在 Snowflake 平台上构建 DeepSeek-R1 聊天机器人。
4.1 设置开发环境
要访问必要的工具,请确保你可以访问 Snowflake 帐户。
接下来,导航到 Snowflake 中的 Streamlit,转到项目→Streamlit,然后单击 + Streamlit App 以创建应用程序(然后你将指定应用程序位置和仓库):
接下来,你将看到一个示例入门应用程序来帮助入门:
Snowflake 中的 Streamlit 界面类似于在线代码编辑器,您可以在左侧编辑代码并在右侧查看呈现的应用程序。
继续将其替换为我们今天要构建的应用程序。
4.2 检索代码
我们今天要构建的 DeepSeek-R1 聊天机器人应用程序由以下部分组成:
- environment.yml — 应用程序的环境依赖项
- streamlit_app.py — Streamlit 应用程序文件
首先,environment.yml 文件的内容如下所示:
name: app_environment
channels:
- snowflake
dependencies:
- python=3.11.*
- snowflake-ml-python
- snowflake-snowpark-python
- streamlit
其次,sis_app.py 文件的内容如下所示:
import streamlit as st
from snowflake.snowpark.context import get_active_session
import pandas as pd
import json
import re
# App configuration
st.set_page_config(page_title="🐳💬 DeepSeek R1 Chatbot", initial_sidebar_state="expanded")
session = get_active_session()
# Helper functions
def clear_chat_history():
st.session_state.messages = [{"role": "assistant", "content": "How may I assist you today?"}]
def escape_sql_string(s):
return s.replace("'", "''")
def extract_think_content(response):
think_pattern = r'<think>(.*?)</think>'
think_match = re.search(think_pattern, response, re.DOTALL)
if think_match:
think_content = think_match.group(1).strip()
main_response = re.sub(think_pattern, '', response, flags=re.DOTALL).strip()
return think_content, main_response
return None, response
def generate_deepseek_response(prompt, **params):
string_dialogue = "".join(
f"{msg['content']}\n\n"
for msg in st.session_state.messages
)
cortex_prompt = f"'[INST] {string_dialogue}{prompt} [/INST]'"
prompt_data = [{'role': 'user', 'content': cortex_prompt}], params
prompt_json = escape_sql_string(json.dumps(prompt_data))
response = session.sql(
"select snowflake.cortex.complete(?, ?)",
params=['deepseek-r1', prompt_json]
).collect()[0][0]
return response
# Model parameters configuration
MODEL_PARAMS = {
'temperature': {'min': 0.01, 'max': 1.0, 'default': 0.7, 'step': 0.01},
'top_p': {'min': 0.01, 'max': 1.0, 'default': 1.0, 'step': 0.01},
'max_tokens': {'min': 10, 'max': 100, 'default': 20, 'step': 10},
'presence_penalty': {'min': -1.0, 'max': 1.0, 'default': 0.0, 'step': 0.1},
'frequency_penalty': {'min': -1.0, 'max': 1.0, 'default': 0.0, 'step': 0.1}
}
# Sidebar UI
with st.sidebar:
st.title('🐳💬 DeepSeek R1 Chatbot')
st.write('This chatbot is created using the DeepSeek R1 LLM model via Snowflake Cortex.')
st.subheader('⚙️ Model parameters')
params = {
param: st.sidebar.slider(
param.replace('_', ' ').title(),
min_value=settings['min'],
max_value=settings['max'],
value=settings['default'],
step=settings['step']
)
for param, settings in MODEL_PARAMS.items()
}
st.button('Clear Chat History', on_click=clear_chat_history)
# Initialize chat history
if "messages" not in st.session_state:
st.session_state.messages = [{"role": "assistant", "content": "How may I assist you today?"}]
# Display chat messages
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.write(message["content"])
# Handle user input
if prompt := st.chat_input():
with st.chat_message("user"):
st.write(prompt)
st.session_state.messages.append({"role": "user", "content": prompt})
if st.session_state.messages[-1]["role"] != "assistant":
with st.chat_message("assistant"):
status_container = st.status("Thinking ...", expanded=True)
with status_container:
response = generate_deepseek_response(prompt, **params)
think_content, main_response = extract_think_content(response)
if think_content:
st.write(think_content)
status_container.update(label="Thoughts", state="complete", expanded=False)
st.markdown(main_response)
st.session_state.messages.append({"role": "assistant", "content": main_response})
你还可以从此 DeepSeek-R1 聊天机器人 Github 存储库下载必要的应用文件。
4.3 运行应用
要运行应用,请复制粘贴上述代码,然后单击“运行”按钮。
你可以将鼠标光标放在代码/应用程序面板的分隔线上,然后将其向左移动,直到代码面板消失(见下文)。这会将应用程序面板扩展至全屏。
继续并输入提示以开始你的聊天会话:
此外,请参阅上面的 Chatbot 实际操作部分,了解 LLM 生成的思维过程和答案。
5、代码说明
让我们探索每个代码块在做什么……
5.1 导入库
我们首先从导入先决条件库开始。
import streamlit as st
from snowflake.snowpark.context import get_active_session
import pandas as pd
import json
import re
5.2 应用程序配置
接下来,我们使用 st.set_page_config() 定义应用程序页面并设置其初始页面参数,我们将设置 initial_sidebar_state="expanded",以便它们完全按照那样做,展开侧边栏。在这里,我们还设置了会话变量,我们稍后会用到它。
# App configuration
st.set_page_config(page_title="🐳💬 DeepSeek R1 Chatbot", initial_sidebar_state="expanded")
session = get_active_session()
5.3 辅助函数
在此部分中,我们定义了几个将在应用程序的后面部分使用的辅助函数:
clear_chat_history()
— 这允许我们将聊天记录清除到初始状态escape_sql_string()
— 在执行一些文本格式化时替换 SQL 字符串extract_think_content()
— 解析并分离包含在 XML 样式“think”标签( 和 )中的内容,并将其与最终响应分开。
# Helper functions
def clear_chat_history():
st.session_state.messages = [{"role": "assistant", "content": "How may I assist you today?"}]
def escape_sql_string(s):
return s.replace("'", "''")
def extract_think_content(response):
think_pattern = r'<think>(.*?)</think>'
think_match = re.search(think_pattern, response, re.DOTALL)
if think_match:
think_content = think_match.group(1).strip()
main_response = re.sub(think_pattern, '', response, flags=re.DOTALL).strip()
return think_content, main_response
return None, response
例如,假设我们有以下生成的响应:
<think>Let me analyze this problem step by step...</think>
Here's the solution you're looking for...
它将解析并分离为:
think_content
:“让我一步一步分析这个问题……”main_response
:“这是您正在寻找的解决方案……”
让我们继续使用最后一个辅助函数:
generate_deepseek_response()
— 使用 Snowflake 的 Cortex 服务和 DeepSeek R1 模型生成 LLM 响应
def generate_deepseek_response(prompt, **params):
string_dialogue = "".join(
f"{msg['content']}\n\n"
for msg in st.session_state.messages
)
cortex_prompt = f"'[INST] {string_dialogue}{prompt} [/INST]'"
prompt_data = [{'role': 'user', 'content': cortex_prompt}], params
prompt_json = escape_sql_string(json.dumps(prompt_data))
response = session.sql(
"select snowflake.cortex.complete(?, ?)",
params=['deepseek-r1', prompt_json]
).collect()[0][0]
return response
5.4 侧边栏 UI
我们首先将 MODEL_PARAMS
变量定义为字典格式,其中包含模型参数以及相关的最小值、最大值、默认值和步长值。
接下来,我们将定义以应用程序标题和应用程序描述开头的侧边栏。在这里,我们还包括几个通过 for 循环迭代创建的滑块小部件。最后,我们有一个清除聊天历史记录按钮,它调用 clear_chat_history
回调函数将历史记录重置为初始状态。
# Model parameters configuration
MODEL_PARAMS = {
'temperature': {'min': 0.01, 'max': 1.0, 'default': 0.7, 'step': 0.01},
'top_p': {'min': 0.01, 'max': 1.0, 'default': 1.0, 'step': 0.01},
'max_tokens': {'min': 10, 'max': 100, 'default': 20, 'step': 10},
'presence_penalty': {'min': -1.0, 'max': 1.0, 'default': 0.0, 'step': 0.1},
'frequency_penalty': {'min': -1.0, 'max': 1.0, 'default': 0.0, 'step': 0.1}
}
# Sidebar UI
with st.sidebar:
st.title('🐳💬 DeepSeek R1 Chatbot')
st.write('This chatbot is created using the DeepSeek R1 LLM model via Snowflake Cortex.')
st.subheader('⚙️ Model parameters')
params = {
param: st.sidebar.slider(
param.replace('_', ' ').title(),
min_value=settings['min'],
max_value=settings['max'],
value=settings['default'],
step=settings['step']
)
for param, settings in MODEL_PARAMS.items()
}
st.button('Clear Chat History', on_click=clear_chat_history)
5.5 聊天元素
在应用程序的最后部分,我们将初始化聊天历史记录的会话状态变量,迭代显示传入的聊天消息,并最终定义处理用户/应用程序聊天逻辑的条件流。后一部分利用先前定义的辅助函数来处理 LLM 生成的响应。
# Initialize chat history
if "messages" not in st.session_state:
st.session_state.messages = [{"role": "assistant", "content": "How may I assist you today?"}]
# Display chat messages
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.write(message["content"])
# Handle user input
if prompt := st.chat_input():
with st.chat_message("user"):
st.write(prompt)
st.session_state.messages.append({"role": "user", "content": prompt})
if st.session_state.messages[-1]["role"] != "assistant":
with st.chat_message("assistant"):
status_container = st.status("Thinking ...", expanded=True)
with status_container:
response = generate_deepseek_response(prompt, **params)
think_content, main_response = extract_think_content(response)
if think_content:
st.write(think_content)
status_container.update(label="Thoughts", state="complete", expanded=False)
st.markdown(main_response)
st.session_state.messages.append({"role": "assistant", "content": main_response})
将这些代码块拼凑在一起,我们就得到了 DeepSeek-R1 聊天机器人!
6、结束语
构建自己的聊天机器人,该聊天机器人由强大的 DeepSeek-R1 模型提供支持。这在不到 100 行代码中令人印象深刻地实现。
你可能会注意到,代码的很大一部分涉及“思考”标签和大量内联注释的处理,如果删除这些注释,应用程序会大大缩小。
原文链接:How to build a DeepSeek-R1 chatbot
汇智网翻译整理,转载请标明出处