分享嘉宾:徐文浩, bothub 创始人
开篇词 & 导读
关于为什么我们要迎接AI爆发的时代 课程模块: 1、通过提示语(Prompt)和嵌入式表示(Embedding)这两个核心功能,看看大模型能帮我们解决哪些常见的任务。通过这一部分,熟悉 OpenAI 的 API,以及常见的分类、聚类、文本摘要、聊天机器人等功能,能够怎么实现。 2、进入真实的应用场景,把自己系统里面的信息,和 AI 系统结合到一起去,以解决和优化实际的业务问题 3、多模态,体验语音识别、语音合成,以及唇形能够配合语音内容的数字人,Stable Diffusion模型等 分享几个 AI 工具:
-
ShareGPT https://sharegpt.com/ 网站,一键分享chatGPT对话片段
-
Poe https://poe.com/login 网站,聊天AI,多种大语言模型可选(Sage、Claude、chatGPT、Dragonfly等)
-
彩云小译 https://fanyi.caiyunapp.com/#/ 浏览器插件,翻译,支持中英文对照(上下文插入的方式,并非左右对照)
-
Glarity https://chrome.google.com/webstore/detail/glarity-summary-for-googl/cmnlolelipjlhfkhpohphpedmkfbobjc/related 浏览器插件,音视频转录文本、总结摘要
-
scispace https://typeset.io/ 网站,论文助手
get ready with me
-
注册并获取你的 openAI 的API账号 https://openai.com/api/
-
下载并安装 python 环境 我使用的是 macos 系统,已经具备 python 环境
-
下载并安装 python 的包管理和环境管理工具 接下来准备一个 python 的包管理和环境管理工具,比如miniconda
mkdir -p ~/miniconda3
curl https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-arm64.sh -o ~/miniconda3/miniconda.sh
bash ~/miniconda3/miniconda.sh -b -u -p ~/miniconda3
rm -rf ~/miniconda3/miniconda.sh
安装后,初始化
~/miniconda3/bin/conda init bash
~/miniconda3/bin/conda init zsh
- 创建一个独立的
python 3.10
环境,并命名为 py310
conda create --name py310 python=3.10
conda activate py310
- 在这个独立环境中安装
jupterlab
、openAI
等后面要用的一系列开发包
pip install jupyterlab==4.0.9
pip install ipywidgets==8.1.1
pip install openai==1.6.1
- 在安装后配置 API key 安装完 JupyterLab 之后,你只需要把刚才我们获取到的 API Key 设置到环境变量里,然后启动 JupyterLab。
export OPENAI_API_KEY=在这里写你获取到的ApiKey
- 打开 JupyterLab,并在浏览器里调试代码 通过 Jupyter Notebook 交互式地运行这个课程后面的代码,体验 OpenAI 的大语言模型神奇的效果。
jupyter-lab .
- 使用 Python 3 的 Notebook
有两种方法: a) 本地搭建一个开发环境 b) 使用 Google 提供的叫做 Colab 的线上 Python Notebook 环境 https://colab.research.google.com/
Colab 可以让你免费使用一些 GPU 的资源,在你需要使用 GPU 尝试训练一些深度学习模型,而又没有一张比较好的显卡的时候,就可以直接使用它。另一方面,Colab 便于你在网络上把自己撰写的 Python 代码分享给其他人。 Colab 已经是一个 Python Notebook 的环境了。所以我们不需要再去安装 Python 和 JupyterLab 了。不过我们还是需要安装 OpenAI 的库,以及设定我们的 API Key。你只需要在 Notebook 开始的时候,执行下面这样一小段代码就可以做到这一点。
!pip install openai
%env OPENAI_API_KEY=在这里写你获取到的ApiKey
不过需要注意,如果你需要将 Notebook 分享出去,记得把其中 OpenAI 的 API key 删除掉,免得别人的调用,花费都算在了你头上。
- 编写代码并运行 可以参考 OpenAI 提供的示例,在上面的开发环境里运行体验一下: https://platform.openai.com/examples
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[
{
"role": "system",
"content": "You will be provided with a description of a mood, and your task is to generate the CSS code for a color that matches it. Write your output in json with a single key called \"css_code\"."
},
{
"role": "user",
"content": "Blue sky at dusk."
}
],
temperature=0.7,
max_tokens=64,
top_p=1
)
大语言模型工作原理分析
大型语言模型的接口其实非常简单。像 OpenAI 就只提供了 Completion
和 Embedding
两个接口。
Completion 可以让模型根据你的输入进行自动续写;
Embedding 可以将你输入的文本转化成向量。
Completion 的参数
OpenAI 的接口文档: https://platform.openai.com/docs/api-reference/completions/create
/** parameter engine: 模型名称,required */
/** parameter prompt: 提示语,required */
/** parameter max_tokens: 调用生成的内容允许的最大token数目 */
/** parameter n: 备选答案 */
/** parameter stop: 停止符号 */
/** parameter temperature: 温度采样 */
/** parameter top_p: 原子核采样,和temperature类似 */
/** parameter suffix: 后缀 */
...
-
参数 max_tokens,你可以简单地把 token 理解成一个单词。实际上,token 是分词之后的一个字符序列里的一个单元。有时候,一个单词会被分解成两个 token。比如,icecream 是一个单词,但是实际在大语言模型里,会被拆分成 ice 和 cream 两个 token。这样分解可以帮助模型更好地捕捉到单词的含义和语法结构。一般来说,750 个英语单词就需要 1000 个 token。注意:max_tokens不能超过模型的上下文长度。且这个数量既包括你输入的提示语,也包括 AI 产出的回答。 我们这里用的 text-davinci-003 模型,允许最多有 4096 个 token。提示语和回答的长度加起来不能超过 4096 个 token。比如,你的输入有 1000 个 token,那么你这里设置的 max_tokens 就不能超过 3096。不然调用就会报错。
-
参数 n,代表你希望 AI 给你生成几条内容供你选择。在这样自动生成客服内容的场景里,我们当然设置成 1。但是如果在一些辅助写作的场景里,你可以设置成 3 或者更多,供用户在多个结果里面自己选择自己想要的。
-
参数stop,代表你希望模型输出的内容在遇到什么内容的时候就停下来,常常会选用 “\n\n"这样的连续换行。
-
聊天AI 每次回复的内容不一样,则归功于我们使用的一个参数 temperature。这个参数的输入范围是 0-2 之间的浮点数,代表输出结果的随机性或者说多样性。top_p 也是随机性参数,两者使用其一即可。
配置 temperature 使回答不呆板(AI 客服)
例如:
from openai import OpenAI
import os
client = OpenAI(api_key = os.environ.get("OPENAI_API_KEY"))
COMPLETION_MODEL = "text-davinci-003"
prompt = '请你用朋友的语气回复给到客户,并称他为“亲”,他的订单已经发货在路上了,预计在3天之内会送达,订单号2021AEDG,我们很抱歉因为天气的原因物流时间比原来长,感谢他选购我们的商品。'
def get_response(prompt, temperature = 1.0, stop=None):
completions = client.completions.create (
model=COMPLETION_MODEL,
prompt=prompt,
max_tokens=1024,
n=1,
stop=stop,
temperature=temperature,
)
message = completions.choices[0].text
return message
相同的提示语,连续调用两次后,给到含义相同、遣词造句不同的结果。
print(get_response(prompt))
亲,您的订单已经顺利发货啦!订单号是 2021AEDG,预计在 3 天之内会寄到您指定的地址。不好意思,给您带来了不便,原计划到货时间受天气原因影响而有所延迟。期待您收到衣服后给我们反馈意见哦!谢谢你选购我们的商品!
亲,您的订单 2021AEDG 刚刚已经发出,预计 3 天之内就会送达您的手中。抱歉由于天气的原因造成了物流延迟,但我们会尽快将订单发到您的手中。感谢您对我们的支持!
若配置 temperature = 0,则每次调用的回答都将得到一致的结果。
print(get_response(prompt, 0.0))
亲,您的订单 2021AEDG 已经发货,预计在 3 天之内会送达。很抱歉因为天气的原因物流时间比原来长,感谢您选购我们的商品,祝您购物愉快! 这样,我们就可以根据具体使用的场景调整 temperature 的值了。
如何实现联系上下文( AI 聊天机器人)
想要实现问答,我们只需要在提示语里,在问题之前加上 “Q :” 表示这是一个问题,然后另起一行,加上 “A :” 表示我想要一个回答,那么 Completion 的接口就会回答你在 “Q : ” 里面跟的问题。
对于聊天机器人来说,只理解当前用户的句子是不够的,能够理解整个上下文是必不可少的。而 GPT 的模型,要完成支持多轮的问答也并不复杂。我们只需要在提示语里增加一些小小的工作就好了———我们把整个对话过程都发送给 AI 来回答(相当于做递归/循环)。
代码可能写成这样:
from openai import OpenAI
import os
client = OpenAI(api_key = os.environ["OPENAI_API_KEY"])
def ask_gpt3(prompt):
response = client.completions.create(
model="text-davinci-003",
prompt=prompt,
max_tokens=512,
n=1,
stop=None,
temperature=0.5,
)
message = response.choices[0].text.strip()
return message
print("你好,我是一个聊天机器人,请你提出你的问题吧?")
questions = []
answers = []
def generate_prompt(prompt, questions, answers):
num = len(answers)
for i in range(num):
prompt += "\n Q : " + questions[i]
prompt += "\n A : " + answers[i]
prompt += "\n Q : " + questions[num] + "\n A : "
return prompt
while True:
user_input = input("> ")
questions.append(user_input)
if user_input.lower() in ["bye", "goodbye", "exit"]:
print("Goodbye!")
break
prompt = generate_prompt("", questions, answers)
answer = ask_gpt3(prompt)
print(answer)
answers.append(answer)
这段代码的意思是,AI 会从命令行读入你的问题,然后给出回答。你可以继续提问,然后我们把整个对话过程都发送给 AI 来回答。你可以尝试着体验一下,AI 是不是能够理解整个对话过程的上下文。你想要退出的时候,就在需要提问的时候,输入 “bye” 就好了。
使用更方便的模型 (gpt-3.5-turbo )实现聊天
在 2023年 3 月 2 日,因为 ChatGPT 的火热,OpenAI 放出了一个直接可以进行对话聊天的接口。这个接口叫做 ChatCompletion,对应的模型叫做 gpt-3.5-turbo,不但用起来更容易了,速度还快,而且价格也是我们之前使用的 text-davinci-003 的十分之一,可谓是物美价廉了。
这里查看 Chat Completions API 官方文档: https://platform.openai.com/docs/guides/text-generation/chat-completions-api
import openai
openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Who won the world series in 2020?"},
{"role": "assistant", "content": "The Los Angeles Dodgers won the World Series in 2020."},
{"role": "user", "content": "Where was it played?"}
]
)
在 OpenAI 的官方文档里,可以看到这个接口也非常简单。你需要传入的参数,从一段 Prompt 变成了一个数组,数组的每个元素都有 role 和 content 两个字段。
role 这个字段一共有三个角色可以选择,其中 system 代表系统,user 代表用户,而 assistant 则代表 AI 的回答。
当 role 是 system 的时候,content 里面的内容代表我们给 AI 的一个指令,也就是告诉 AI 应该怎么回答用户的问题。比如我们希望 AI 都通过中文回答,我们就可以在 content 里面写“你是一个只会用中文回答问题的助理”,这样即使用户问的问题都是英文的,AI 的回复也都会是中文的。
而当 role 是 user 或者 assistant 的时候,content 里面的内容就代表用户和 AI 对话的内容。和我们在第 03 讲里做的聊天机器人一样,你需要把历史上的对话一起发送给 OpenAI 的接口,它才能有理解整个对话的上下文的能力。
我们在下一篇详细了解如何制作一个聊天机器人。
论文精读
如果你想知道 GPT 系列大模型到底是怎么回事儿,可以看一下李沐老师讲解 GPT 系列论文的视频
- GPT、GPT-2、GPT-3 论文精读: https://www.bilibili.com/video/BV1AF411b7xQ/
- GPT-4 论文精读: https://www.bilibili.com/video/BV1vM4y1U7b5/