聊天机器人
- 背景
- 机器学习基础
- 监督学习(Supervised Learning)
- 概念
- 应用场景
- 主要问题
- 无监督学习(Unsupervised Learning)
- 概念
- 常见方法
- 应用场景
- 强化学习(Reinforcement Learning)
- 概念
- 关键要素
- 应用场景
- 模型优化
- Transformer:现代 NLP 的核心
- Transformer 的特点
- 大语言模型(LLM)的应用
- Token 统计工具
- 大语言模型的优化流程
- 步骤 1:监督微调(Supervised Fine - Tuning)
- 步骤 2:训练奖励模型(Training a Reward Model)
- 步骤 3:优化策略(Optimize Policy)
- Streamlit 介绍
- 安装 Streamlit
- 示例代码(helloworld)
- 运行应用
- 运行结果示例
- 聊天机器人
- OpenAI API 参考
- 运行代码和效果
- 代码
- 界面运作原理
- 动画效果
背景
学习大模型已经有一两个月了,为了加深理解,最近开始了一些实践。通过跟随一个bilibili的教程,逐步实现了一个最simple的 AI 聊天机器人。本篇文章主要梳理看视频过程中的机器学习的基础知识,并介绍一些其他的基础知识,只为备忘。
机器学习基础
监督学习(Supervised Learning)
概念
监督学习是指使用标注数据进行训练,并通过测试数据集来检验模型效果。
应用场景
- 分类(Classification):如垃圾邮件分类、图片识别等。
- 回归(Regression):如房价预测、天气预测等。
主要问题
- 标注数据成本高昂:标注数据需要大量人工干预,且成本较高。
- 泛化能力有限:模型容易在训练数据上表现良好,但在新数据上效果差,容易发生过拟合。
- 无法处理无标签数据:监督学习方法依赖标签,因此不能直接应用于无标签数据的场景。
无监督学习(Unsupervised Learning)
概念
无监督学习无需依赖标注数据,模型通过分析数据本身的结构和规律进行学习,主要用于挖掘数据中潜在的模式。
常见方法
- 聚类(Clustering):如 K-means、层次聚类。
- 关联规则(Association Rules):如市场购物篮分析(购买电动牙刷后推荐牙膏)。
应用场景
- 推荐系统:根据用户行为推荐商品。
- 数据降维:如 PCA(主成分分析)优化数据特征。
- 医疗分析:从患者数据中发现潜在的疾病关联。
强化学习(Reinforcement Learning)
概念
强化学习通过与环境的交互学习最优策略,以最大化奖励。它不像监督学习那样需要标注数据,而是通过试错过程不断优化决策策略。
关键要素
- 状态(State):描述环境的当前情况。
- 动作(Action):智能体可以选择的操作。
- 奖励(Reward):智能体执行某个动作后从环境中获得的反馈,通常用于评估该动作的效果。
应用场景
- 自动驾驶:通过与环境交互来不断优化驾驶策略,提高决策能力。
- 游戏 AI:例如 AlphaGo 通过自我对弈学习最优策略,最终战胜顶级围棋选手。在游戏的每个步骤中根据当前的环境状态,考虑当前随后的不同操作(还需要同时兼顾所有历史的操作),不同的操作有不同的得分反馈。
模型优化
在机器学习中,模型的效果通常受到以下三种情况的影响:
- 欠拟合(Underfitting):模型过于简单,无法捕捉数据中的规律,导致训练误差和测试误差都较高。
- 过拟合(Overfitting):模型在训练数据上表现良好,但对未见数据的泛化能力差,测试误差较大。
- 最佳拟合(Optimal Fit):模型在训练集和测试集上都能保持较好的表现,具备良好的泛化能力。
Transformer:现代 NLP 的核心
Transformer 的特点
- 全局注意力机制:相比于 RNN,Transformer 能够更好地捕捉长距离的依赖关系,不再依赖顺序性,显著提高了训练效率。
- 并行计算:Transformer 支持并行计算,极大地提升了训练和推理的速度,特别是在大规模数据集上。
大语言模型(LLM)的应用
基于 Transformer 的大语言模型(LLM)具有强大的文本处理能力,能够在以下任务中发挥作用:
- 特征提取:从大量文本中提取有用的特征。
- 文本生成(AIGC):生成高质量的自然语言文本。
- 问答系统(QA):自动回答用户提出的问题。
- 文本分类:对文本进行类别分类。
- 文本摘要:从长篇文本中提取出核心信息。
- 机器翻译:自动将一种语言翻译成另一种语言。
Token 统计工具
在处理 LLM 任务时,Token 统计是必不可少的。推荐使用以下工具来进行 Token 计算:
GPT Tokenizer
大语言模型的优化流程
训练一个强大的 LLM 需要经历以下三个步骤:
步骤 1:监督微调(Supervised Fine - Tuning)
- 数据收集:收集人类示范数据(Collect human demonstration data),即人类针对特定提示(Prompt)给出的答案。
- 模型微调:使用这些人类示范数据对基础大语言模型(Base LLM)进行监督微调,得到监督微调模型(SFT,Supervised Fine - tune)。这一步属于监督学习的范畴。
步骤 2:训练奖励模型(Training a Reward Model)
- 偏好数据收集:模型(SFT)针对提示生成多个答案(Answer 1、Answer 2 等),由人类对这些答案进行偏好排序,收集人类偏好数据(Collect human preference data)。
- 奖励模型训练:基于收集到的人类偏好数据,训练一个独立的奖励模型(RM,Reward Model)。这个过程同样是在基础大语言模型的基础上进行微调。
步骤 3:优化策略(Optimize Policy)
- 策略更新:使用强化学习算法(如近端策略优化算法 PPO,Proximal Policy Optimization),在奖励模型(RM)的反馈下更新模型策略(Policy)。模型根据提示(Prompt)生成答案(Answer),奖励模型会根据答案的质量给予奖励(Reward),强化学习算法根据奖励信号来优化模型,使其生成更符合人类偏好的答案。
通过这三个步骤,RLHF 使得模型能够更好地理解和满足人类的需求与偏好,提升生成内容的质量和适用性。
作为一个学习 LLM 的新人,上述逻辑还是让我感觉到很牛的。我们只需要训练好一个BaseLM,这个BaseLM可以作为积木的基础,用以实现模型进化。它的思想是先使用BaseLM(命名为
A
A
A) SFT一个微调模型
B
B
B,利用微调模型对预定的每个问题得到多个答案,然后利用人类对答案进行打分,这些问题和打分过的答案又可以作为数据源对BaseLM进行微调,以得到一个奖励模型(其实就是打分模型,命名为
C
C
C);最后我们利用奖励模型
C
C
C来对微调模型
B
B
B的输出进行自动打分,利用强化学习的思想使得微调模型
B
B
B不断进化。
A
→
S
F
T
→
B
A
→
人类打分
S
F
T
→
C
B
→
R
L
→
B
+
(
利用
C
来打分反馈
)
\begin{split} & A \rightarrow SFT \rightarrow B \\ & A \rightarrow 人类打分SFT \rightarrow C \\ & B \rightarrow RL \rightarrow B^+ ( 利用 C 来打分反馈) \\ \end{split}
A→SFT→BA→人类打分SFT→CB→RL→B+(利用C来打分反馈)
Streamlit 介绍
Streamlit 是一个用于构建快速、交互式 Web 应用的 Python 库,特别适用于机器学习和数据科学项目。通过简单的 Python 代码,Streamlit 可以让你快速展示数据可视化、创建交互式界面和展示机器学习模型的结果。总的来说是可以用于快速验证思路,进行demo展示。
安装 Streamlit
你可以通过以下命令安装 Streamlit:
pip install streamlit
示例代码(helloworld)
以下是一个简单的 Streamlit 示例,展示了如何快速创建一个简单的 Web 应用:
import streamlit as st
st.title("Streamlit 示例应用")
st.write("""
# My First Go Program
Hello World!
""")
运行应用
运行以下命令启动 Streamlit 应用:
streamlit run streamlit_app.py
运行结果示例
聊天机器人
下面不到100行的代码,就实现了聊天机器人的web应用,简单、高效。
其中一个注意的地方是:这里我使用本地的ollama+qwen2.5:0.5b来实现,你可以替换为 deepseek 或者 openai 的官方API。
client = OpenAI(api_key=“ollama”, base_url=“http://localhost:11434/v1/”)
OpenAI API 参考
使用 OpenAI 提供的 API 可以方便地调用大语言模型:OpenAI API 文档
运行代码和效果
streamlit run chatbot.py
代码
import streamlit as st
from openai import OpenAI
client = OpenAI(api_key="ollama",
base_url="http://localhost:11434/v1/")
# 定义左侧边栏
with st.sidebar:
st.markdown(f"""
<center>
<img src='https://vip.helloimg.com/i/2024/07/02/66841f6f4a3a5.png' width='100'/>
<h1>MoBot <sup>®</sup></h1>
</center>
""", unsafe_allow_html=True)
# 角色定义输入框 System Message
system_message = st.text_area("角色定义", "你是一个能帮助用户的 AI 助手。")
# 创造力调节 Temperature
temperature = st.slider("创造力调节", min_value=0.0, max_value=2.0,
value=1.0, step=0.1, help='值越大越具有创造力', format="%.1f")
# 清除历史消息记录按钮
if st.button("清除历史消息记录"):
st.session_state.messages = [
{
"role": "system",
"content": system_message
},
{
"role": "assistant",
"content": "Hi. 我是 Mobot~ 很高兴遇见你!有问必答,专注于懂你的 AI 🤗"
}
]
# 定义右边的 chatbot 对话窗口标题
st.title("🤖 AI 聊天机器人")
# 初始化界面的聊天列表
if "messages" not in st.session_state:
st.session_state.messages = [
{
"role": "system",
"content": system_message
},
{
"role": "assistant",
"content": "Hi. 我是 Mobot~ 很高兴遇见你!有问必答,专注于懂你的 AI 🤗"
}
]
# Display chat messages from history on app rerun
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.markdown(message["content"])
# 用户输入
user_query = st.chat_input("说点什么...")
if user_query:
# 正确更新 system message
st.session_state.messages[0] = {
"role": "system",
"content": system_message
}
# 显示用户输入的内容到聊天窗口
with st.chat_message("user"):
st.write(user_query)
# 在聊天窗口输出用户输入的问题
st.session_state.messages.append({"role": "user", "content": user_query})
with st.chat_message("assistant"):
with st.spinner("AI 正在思考..."):
print("---------------\n", st.session_state.messages)
# 发送请求到API
response = client.chat.completions.create(
model="qwen2.5:0.5b",
messages=st.session_state.messages,
temperature=temperature,
stream=True
)
message_placeholder = st.empty()
ai_response = ''
for chunk in response:
chunk_message = chunk.choices[0].delta.content if chunk.choices and chunk.choices[0].delta.content else ''
ai_response += chunk_message
message_placeholder.markdown(ai_response)
# 将AI的回复添加到消息历史
st.session_state.messages.append(
{"role": "assistant", "content": ai_response})
界面运作原理
- 初始化:应用启动时,会初始化侧边栏、聊天窗口标题和聊天记录。
- 显示历史记录:将 st.session_state.messages 中的历史聊天记录显示在聊天窗口中。
- 等待用户输入:用户在输入框中输入消息,点击发送后,消息会显示在聊天窗口中,并添加到 st.session_state.messages 列表中。
- 获取 AI 回复:应用将包含用户输入的完整聊天记录发送到 OpenAI API,获取 AI 的回复,并将回复显示在聊天窗口中,同时添加到 st.session_state.messages 列表中。
- 清除历史记录:用户点击侧边栏的 “清除历史消息记录” 按钮,将 st.session_state.messages 重置为初始状态,聊天窗口中的历史记录被清空。
通过这种方式,用户可以持续与 AI 进行对话,并且可以随时调整角色定义和创造力参数,或者清除历史记录。
动画效果
备注:过去该文章有一段关于 RAG 描述,相关内容已经全部汇总到另外一篇文章RAG实践,欢迎移步。