KeyWords
1. Prompt
ChatGPT出现后,Prompt都指每次访问大模型时的输入。而大模型的返回结果被称作Completion
2. Temperature
LLM生成是具有随机性的,在模型的顶层通过选取不同预测概率的预测结果来生成最后的结果。我们通过温度系数Temperature来控制LLM生成结果的随机性和创造性。
Temperature一般取值0~1之间,当取值较低,预测随机性较低,产生更保守,可预测的文本,不太可能生成意想不到或不寻常的词。相反,当取值较高时,预测随机性较高,所有词被选择的可能性更大,会产生更有创意,多样化的文本,更有可能生成不寻常的词。
3. System Prompt
一种大模型服务方为提升用户体验所设置的一种策略:System Prompt内容会在整个会话过程中持久地影响模型的回复,且相比于普通Prompt具有更高的重要性。User Prompt更偏向于平时的prompt,即需要做出回复的输入。
一般来说,我们用System Prompt来对模型进行一些初始化设定,例如,我们可以在System Prompt 中给模型设定我们希望它具备的人设,比如个人知识库助手等。
一般System Prompt在一个会话中只会有一个。
调用大模型API
申请各平台apikey的教程在动手学大模型应用开发 (datawhalechina.github.io)的第二章有,不多赘述
各家接口不同,对应的api-key也各不相同,各自的格式如下:
平台/模型名 | APPID | Secret KEY | API KEY |
---|---|---|---|
ChatGPT | sk-************ | ||
百度文心 | ************ | ************ | |
讯飞星火 | ******** | ************ | ************ |
智谱AI | ************.************ |
基于原生接口调用
各家的模型都有原生的接口,标准相差很多
ChatGPT
调用ChatGPT需要使用ChatCompletion API,调用方法:
completion = openai.ChatCompletion.create(
# 创建一个 ChatCompletion
# 调用模型:ChatGPT-3.5
model="gpt-3.5-turbo",
# message 是你的 prompt
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Hello!"}
]
)
参数:
- model:调用的模型
- message:prompt
- temperature:温度系数
- max_tokens,最大token数,OpenAI计算的是Prompt + Completion的总token数,要求总token数不能超过模型上限(比如4096),如果输入较长,则需要设置较小的max_tokens,避免总token超限
ChatGPT需要设置Proxy,可以通过os.environ进行设置,或者设置openai中的proxy
API返回的ChatComletion对象,该对象包含的信息格式可以当作json读取:
{
"choices": [
{
"finish_reason": "stop",
"index": 0,
// 回复信息
"message": {
"content": "Hello! How can I assist you today?",
"role": "assistant"
}
}
],
// 创建时间
"created": 1695112507,
"id": "chatcmpl-80QUFny7lXqOcfu5CZMRYhgXqUCv0",
// 模型类型
"model": "gpt-3.5-turbo-0613",
"object": "chat.completion",
// 花费,分别以及共有多少token
"usage": {
"completion_tokens": 9,
"prompt_tokens": 19,
"total_tokens": 28
}
}
百度文心
百度文心刚开始送了18元代金券,并且实名认证后还会再给50。但是按照Datawhale的代码运行会遇到一些问题:
- 首先是第一次运行
get_wenxin("你好")
时,会报错,'result'
这是可以通过改动get_wenxin中的代码,print(js)来查看错误信息。因为是access_token
未改动的原因,需要手动给access_token替换成对应值。 - 第二次运行时还会报一个错误,就是daily limit reached之类的,就是达到运行上限了
这里是需要在计费管理开通文心大模型的付费服务,让它能扣你的代金券才能继续跑(这个问题是我在运行LangChain调用文心时发现的)
文心的模型调用是不需要额外安装别的库的,直接通过网址进行请求即可。不过也对应的增加了一层验证。整体流程为:通过api_key和secret_key获取access_token(一般是一个月过期或者流量用完过期)然后基于access_token即可调用文心大模型。
请求access_token代码:
def get_access_token():
"""
使用 API Key,Secret Key 获取access_token,替换下列示例中的应用API Key、应用Secret Key
"""
# 指定网址
url = "https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id={api_key}&client_secret={secret_key}"
# 设置 POST 访问
payload = json.dumps("")
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
# 通过 POST 访问获取账户对应的 access_token
response = requests.request("POST", url, headers=headers, data=payload)
return response.json().get("access_token")
```
调用百度文心接口代码:
```python
# 一个封装 Wenxin 接口的函数,参数为 Prompt,返回对应结果
def get_completion_weixin(prompt, temperature = 0.1, access_token = ""):
'''
prompt: 对应的提示词
temperature:温度系数
access_token:已获取到的秘钥
'''
url = f"https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/eb-instant?access_token={access_token}"
# 配置 POST 参数
payload = json.dumps({
"messages": [
{
"role": "user",# user prompt
"content": "{}".format(prompt)# 输入的 prompt
}
],
"temperature" : temperature
})
headers = {
'Content-Type': 'application/json'
}
# 发起请求
response = requests.request("POST", url, headers=headers, data=payload)
# 返回的是一个 Json 字符串
js = json.loads(response.text)
# print(js)
return js["result"]
讯飞星火
因为星火API需要通过websocket进行连接,讯飞给出了配置示例SparkApi.py和连接示例test.py,我们仅看test.py中的调用逻辑,配置示例代码直接使用即可。
星火需要的密钥包含三个:appid, secret_key, api_key
除了websocket设置比较麻烦意以外,其余并没有特别不同。
智谱AI
利用zhipuai的原生api调用,设置zhipuai.api_key
即可,很方便
智谱AI生成embedding
zhipuai.model_api.invoke
时model用text_embedding
即可
另外就是token与字数的换算比例,一般是1:1.8左右
基于LangChain调用大模型
LangChain调用模型的流程为:在Model I/O中,根据LLM创建ChatModel,然后输入Prompt,用Output Parser提取信息。
ChatGPT
由于LangChain已经为openai准备了LLM和ChatModel,我们直接创建ChatModel,再通过Prompt中的Template模板化输入即可得到返回值。
我们设置一个用于文本翻译的Template(这种写法是一种定式,可以较大程度发挥模型性能。看起来就是利用原始字符串
来自定义文本及变量,并且文本的语法有所规范)我们设一个变量text,用于指向用户输入,这样便可以实现自动化的任务部署分发。
完成Template后,我们针对模型调用format方法,将template转化为模型输入形式,在ChatGPT中就是message格式(需要role, content, assistance)
# 从chat_models中导入对话模型,其他模型见api文档:
# https://api.python.langchain.com/en/latest/api_reference.html#module-langchain.chat_models
from langchain.chat_models import ChatOpenAI
chat = ChatOpenAI(temperature=0.0)
# 从Prompt Template导入模版
from langchain.prompts import ChatPromptTemplate
# 我们先构造一个个性化模板,用于对给定文本进行中文翻译
template_string = """Translate the text \
that is delimited by triple backticks \
into a Chinses. \
text: ```{text}```"""
chat_template = ChatPromptTemplate.from_template(template_string)
text = "Today is a nice day"
#调用format_message将template转化为message格式
message = chat_template.format_messages(text=text)
response = chat(message)
其中ChatOpenAI模型常用超参:
- model_name=‘gpt-3.5-turbo’,模型名,同原生接口
- temperature,温度系数,同原生接口
- openai_api_key,设置API-KEY
- openai_proxy,设置代理
- streaming=False,流式传输,逐字输出模型回答
- max_tokens,模型输出的最大token数,同原生接口
百度文心
因为LangChain不支持直接调用文心的模型,所以需要自定义一个LLM。
这个LLM应当可以从api_key和secret_key开始,申请access_token,并发起请求调用大模型。另外还应当可以存储默认参数并修改,终点是输入prompt,得到completion。
并且接下来利用LangChain调用大模型的案例大同小异,所以我们的重点会是如何自定义LLM之类更加底层的过程。
讯飞星火
讯飞的LLM只有websocket连接部分比较复杂,请求头以及request较为简单。
智谱AI
需要结合zhipuai库进行调用,添加了流支持和callback,这部分较为复杂,后续细学了LangChain再看
智谱AI生成embedding
比前者简单的多,基本只是简单封装
LangChain组件详解
见Datawhale的总结文章7. LangChain 组件详解 (datawhalechina.github.io)
LangChain自定义LLM
对于自定义的LLM,只有一个必须要实现的就是_call
函数,该函数输入一个字符串,一些可选的停止词,然后返回一个字符串
此外还有一个可选项是_identifying_params
,返回一个字典,可以帮助打印这个类
详细代码见附1. LangChain自定义LLM (datawhalechina.github.io)
将大模型API封装成本地API
基于pydantic的BaseModel,将模型所需配置的参数及Prompt封装成Item,利用FastAPI创建一个post请求的API端点(该端点添加async以支持并行运行),该函数输入为Item类,返回为response,这里是一个字符串。
LangChain自定义Embedding
zhipuai由于需要通过环境变量读取api_key,所以通过pydantic中的root_validator装饰器在对Model校验之前进行自定义数据校验,函数应该返回一个字典,包含经过校验的数据,校验失败则抛出ValueError异常
其余比较重要的是self.client如何定义的,是在这个数据校验的函数中顺便给zhipiai.model_api给赋值进去了