OpenAI

Link

OpenAI最核心的功能,就是它所提供的文本生成模型。模型经过训练可以理解自然语言、代码和图像。模型可以接受任意类型的输入,最终输出文本。

使用模型,你可以构建任意你所需要的AI应用程序,比如:

1.编写文案

2.编写编程代码

3.回答知识库问题

4.分析文本

5.日常助手

6.语言翻译

01第一个聊天程序

ChatCompletion的输入是一个message list,返回是一个chatCompletion对象,示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#openai默认的声明方式,注册openai后在对应的控制台获取api_key
from openai import OpenAI
client = OpenAI(api_key="sk-")

# 通常我会把自己的API-KEY放在.env文件里,然后gitignore掉。
# .env文件可以通过 dotenv库来读取,然后放进系统变量里,这样OpenAI就可以直接识别
from dotenv import load_dotenv, find_dotenv
load_dotenv(find_dotenv())
client = OpenAI()
#当然也可以通过openai调用本地运行的大模型,只要找到对应的url以及model name就行
#以ollama为例(注意要先启动ollama server哦)
client = OpenAI(
base_url = 'http://localhost:11434/v1', # ollama 默认端口
api_key='---', # openai需要填的,但填什么都可以,不会进行验证
)

response =clinent.chat.completions.create(
model = 'model_name',
messages=[
{"role":"user","content":"quary"} # quary就是你提的问题
],
)
print(response)
print(response.choices[0].message.content)
参数 是否必填 数据类型 注释
model 必填 string 需要使用的模型ID。ollama list可以查看。openai里也有很多,还有就是阿里云的百炼平台也提供(有免费额度)
messages 必填 array 包括所有的对话列表。目前,openai提供的message role有:system、user、assistant、tool类型,用于区分是系统级别的消息、ai助手级别的消息、还是用户级别的消息。在许多场景下,需要包含历史记录,所以一般都会吧所有的用户问题和ai返回的消息,一起append到messages中,再进行下一次提问。
max_tokens 可选 integer or null 返回结果的最大token数量。可以降低一定的成本
tools 可选 array 模型可能调用的function call。最多支持128个function call。
logprobs 可选 boolean or null 是否输出结果的对数概率,如果为true,则返回消息内容中返回的每个输出标记的对数概率,默认值为false
top_logprobs 可选 map or null 修改指定token出现的可能性
n 可选 integer or null 模型返回结果数。默认值为1

02stream流式响应

1
2
3
4
5
6
7
8
9
10
11
12
response =clinent.chat.completions.create(
model = 'model_name',
messages=[
{"role":"user","content":"quary"} # quary就是你提的问题
],
stream=True
)

for chunk in response:
if chunk.choice[0].delta.content is not None:
print(chunk.choices[0].delta.content,end="")
print(json.dumps(response.to_dict(),indent=4))

03messages对象

messages对象,它是一个对象数组,其中每个对象有一个role和一个content。user、assistant、tool。常用的就是system、user、assistant这3个。

  • system 如果你的系统是一个通用系统,可以不指定system的内容。如果您是一个私有化场景下的AI系统,可指定system的内容,比如:如果您是一个AI办公系统,可以指定system内容:

    `你是一家公司的行政人员,需要处理公司日常的工作,请使用专业的办公用语进行回复

  • user 所有用户的信息

  • assistant 所有由大模型返回的信息

messages中一个比较重要的知识点就是为了承接上下文,一般我们会把聊天记录都传递给模型,从而可以实现对历史记录的回答。

04seed参数

  • seed参数(类似一个随机种子) beta(测试阶段)
  • system_fingerprint:在response中,注意一下system_fingerprint的值,看看是否变化,如果没有变化,则表示是同样一次相同的会话。
1
2
3
4
5
6
7
8
response =clinent.chat.completions.create(
model = 'model_name',
messages=[
{"role":"user","content":"quary"} # quary就是你提的问题
],
seed = 123
)
print(response.system_fingerprint)

05openai_response_format

默认情况下,openai会将结果以string的格式返回,我们可以通过response.choices[0].message.content获取该值,从而获取数据后进行其他函数调用。当然,你可以在messages中,通过system role或者在prompt中,指定返回json的格式,但是模型不能100%保证生成json对象的可靠性,也就是说,通过prompt指定返回json格式,有可能会获取到不是json格式的结果。

在GPT4和GPT3.5版本中支持使用respond_format,指定openai返回json对象格式,模型会保证结果是一个标准的json结构

1
2
3
4
5
6
7
response =clinent.chat.completions.create(
model = 'model_name',
messages=[
{"role":"user","content":"quary"} # quary就是你提的问题
],
response_format=["type":"json_object"]
)

06max_tokens

openai的收费标准,也是按照输入输出的token数量进行收费的。

max_token 限制模型输出长度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from openai import OpenAI

client = OpenAI(api_key = "sk-")

response = client.chat.completions.create(
model = "gpt-4-0125-preview",
messages=[
{"role":"user","content":"quary"} # quary就是你提的问题
],
max_tokens=10
)

print(respones.choices[0].message.content)
print("input tokens:" + str(response.usage.prompt_tokens) +
"output tokens:" + str(response.usage.completion_tokens) +
"total tokens:" + str(response.usage.total_tokens)
)
print(response.choices[0].finish_reason)

07logprobs&top_logprobs

模型response返回的内容,每一个token,都会有一个自己的logprobs,最终返回所有的内容给用户。

  • logprobs,称之为对数概率,如果您设置位true,模型将显示生成的每个token概率。返回值的概率约接近100%,则代表模型的对于该问题的回答越有信心。

  • top_logprobs,取值范围为0-20,指定每个token位置最有可能返回的标记数量以及每个token的对数概率

  • 由于对数概率的数值,一般人难以看懂,我们还是比较适合看百分比的数据,所以为了直观感受数值,我们需要将对数概率转换成百分比数值

1
2
3
4
5
def lograbs_to_percentage_str(logprobs):
"""

"""

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from openai import OpenAI

client = OpenAI(api_key = "sk-")

response = client.chat.completions.create(
model = "gpt-4-0125-preview",
messages=[
{"role":"user","content":"quary"} # quary就是你提的问题
],

)

print(respones.choices[0].message.content)
print("input tokens:" + str(response.usage.prompt_tokens) +
"output tokens:" + str(response.usage.completion_tokens) +
"total tokens:" + str(response.usage.total_tokens)
)
print(response.choices[0].finish_reason)

08结构化输出

新的结构化输出功能旨在确保模型生成的输出与提供的JSON格式匹配。

1
2
3
4
5
6
7
8
9
10
11
12
# 定义json格式

{
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"email": {"type": "string", "format": "email"}
},
"required": ["name", "age", "email"]
}

设置API请求
设置一个 API 请求,指示模型生成与此模式匹配的数据。使用带有 json_schema 选项的 response_format 参数来强制执行结构。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def generate_profile():
schema = {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"email": {"type": "string", "format": "email"}
},
"required": ["name", "age", "email"]
}

response = openai.Completion.create(
model="gpt-3.5-turbo",
prompt="Generate a user profile:",
response_format={"json_schema": schema},
max_tokens=100
)

return response['choices'][0]['message']['content']

print(generate_profile())

将函数调用与结构化输出一起使用

利用结构化输出的另一种方法是通过函数调用。这种方法允许您根据提供的模式定义模型可以调用的特定函数。以下是实现方法:

1
2
3
4
5
6
7
8
# 定义函数
def create_user_profile(name, age, email):
return {
"name": name,
"age": age,
"email": email
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 注册工具函数
tools = [
{
"type": "function",
"function": {
"name": "create_user_profile",
"description": "Create a user profile with name, age, and email.",
"parameters": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"email": {"type": "string", "format": "email"}
},
"required": ["name", "age", "email"]
}
}
}
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 生成输出

import jsonschema
from jsonschema import validate

def validate_profile(profile, schema):
try:
validate(instance=profile, schema=schema)
print("Profile is valid.")
except jsonschema.exceptions.ValidationError as err:
print("Profile is invalid:", err)

# Example usage
profile = generate_profile_with_function_calling()
validate_profile(json.loads(profile), schema)

附录

开源项目 chat with sql 缺陷在schema上,LLM上下文窗口是有长度限制的, 后续会进行优化