掘金 后端 ( ) • 2024-04-28 10:45

theme: qklhk-chocolate

前言

回顾上上篇文章写到如何实现最简单的OpenAI对话请求示例:

使用 Python接入 OpenAI API,梳理清楚对话角色&函数调用

使用 Python接入 OpenAI API,实现简单的对话生成,介绍其中相应参数含义

from openai import OpenAI
from dotenv import load_dotenv, find_dotenv

_ = load_dotenv(find_dotenv())
client = OpenAI()

response = client.chat.completions.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?"}
  ]
)
print(response)  # 打印的是一个对象
print(response.choices[0].message.content)  # 打印的是一个具体的回复的内容

今天来探究一下token计算和completions接口其他的参数详细含义

token

根据上面的例子返回的内容为

ChatCompletion(id='chatcmpl-9IcMQtYPGYI0cOQCTENdbvO0M2yFx', choices=[Choice(finish_reason='stop', index=0, logprobs=None, message=ChatCompletionMessage(content='The 2020 World Series was played in Globe Life Field in Arlington, Texas.', role='assistant', function_call=None, tool_calls=None))], created=1714224390, model='gpt-3.5-turbo-0125', object='chat.completion', system_fingerprint='fp_3b956da36b', usage=CompletionUsage(completion_tokens=17, prompt_tokens=53, total_tokens=70))
The 2020 World Series was played in Globe Life Field in Arlington, Texas.

只有接口返回时候才知道输入使用了53个token,输出使用了17个token,看起来一个token表示一个或者多个字符,究竟如何计算参考OpenAI 官方文档:

https://platform.openai.com/docs/guides/text-generation/managing-tokens

官方示例:"ChatGPT is great!" 这个句话被拆解成6个token: ["Chat", "G", "PT", " is", " great", "!"].

实际的计算要利用到一个第三方包:tiktoken

文档ChatGPT 利用了三个编码器对文本进行了编码:

编码名称 OpenAI 模型名称 cl100k_base gpt-4gpt-3.5-turbotext-embedding-ada-002text-embedding-3-smalltext-embedding-3-large p50k_base Codex models, text-davinci-002, text-davinci-003 r50k_base (or gpt2) GPT-3 models like davinci

看起来目前主流的ChatPGT模型就是用 `cl100k_base`编码来获取文本占用的token,接下来用代码实际计算token。

先安装这个包

pip install --upgrade tiktoken
import tiktoken 
encoding = tiktoken.get_encoding("cl100k_base")

# 或者
# encoding = tiktoken.encoding_for_model("gpt-3.5-turbo")

def get_token_data(words):
    resource_data = encoding.encode(words)
    len_data = len(resource_data)
    print("%s 编码后内容:%s"%(words, resource_data))
    print("%s 编码后token个数:%s"%(words,len_data))
    return len_data

words_1 = '请说王子请睡觉'
words_2 = 'tiktoken is great!'
get_token_data(words_1)
get_token_data(words_2)

打印内容:

请说王子请睡觉 编码后内容:[15225, 37687, 29207, 233, 45829, 15225, 84949, 94, 19658, 231]
请说王子请睡觉 编码后token个数:10
tiktoken is great! 编码后内容:[83, 1609, 5963, 374, 2294, 0]
tiktoken is great! 编码后token个数:6

这样是不是更清楚token的消耗计算了呢?

其他参数

参考OpenAI 官方文档:

https://platform.openai.com/docs/api-reference/chat/create

一共用20个参数:

messages,model,frequency_penalty,logit_bias,logprobs,top_logprobs,max_tokens,n,presence_penalty,response_format,seed,stop,stream,temperature,top_p,tools,tool_choice,user,function_call,functions

除去必需两个参数messages,model,其他的stream**,**function_call,functions,tool_choice,tools,response_format前面两天了解过不做介绍,其他参数分为两个部分,一部分为控制参数:

  • frequency_penalty(数字或null,默认0):惩罚概率,控制模型重复生成相同文本的倾向。值越高,重复的可能性越小。

  • logit_bias(字典):调整模型输出文本的概率分布。它本质上是一个 映射表,用于 调整特定词语 在生成文本中的出现 可能性

  • max_tokens:参数用于控制模型生成文本的最大长度。它以令牌(tokens)为单位进行衡量,通常用于控制回复长度和计算资源。

  • n(整数,默认值:1):指示模型应生成多少个不同的文本版本。

  • presence_penalty(数字或者null,默认0):类似于 frequency_penalty,但会惩罚生成的文本中重复的 n-gram(词序列)。

  • seed(整数):一个随机种子值。使用相同的种子值会始终生成相同的文本序列。

  • stop(字符串数组):一个字符串数组,充当终止条件。如果模型在输出中遇到任何这些字符串,它将停止生成文本。

  • temperature(0到2之间,默认值:1.0):控制生成文本的创造性。值越高,文本越具创意和出人意料,但可能与给定提示的相关性较低。值越低,文本越保守和可预测。

  • top_p(浮点数,0.0-1.0,默认值:1.0):通俗地说,top_p 参数就像一个筛选器,用于控制 OpenAI 模型生成文本时的"冒险程度",0 表示最保守,1 表示最冒险。

  • user 模型微调相关,用户关联数据相关

另一部分为高级参数(用作调试)

  • logprobs(整数,或者null,默认null):当设置为 true 时,模型会提供每个生成词的概率值 (logprob)。

  • top_logprobs(整数,或者null,默认null):控制与每个词一起返回的概率数量(对于下一个 N 个词)。例如,top_logprobs=2 会在每个生成词之后返回下一个两个词的概率。

top_logprobslogprobs 是OpenAI API 新增的参数可以帮助我们理解和调试大模型的输出结果,减轻幻觉问题,提高输出的确定性和可靠性。

其中比较重要的参数有**temperature,top_p**,在很多第三方工具都有见到这两个参数,现在测试一下

代码如下:

from openai import OpenAI
from dotenv import load_dotenv, find_dotenv

_ = load_dotenv(find_dotenv())
client = OpenAI()

response = client.chat.completions.create(
  model="gpt-3.5-turbo",
  temperature=0,
  top_p=1,
  messages=[
    {"role": "system", "content": "你是一个人工智能助手,你帮助用户回答问题。"},
    {"role": "user", "content": "你是谁"},
  ]
)
print(response.choices[0].message.content) 
# 统一询问大多都是统一回复
# 我是一个人工智能助手,可以帮助您回答问题和提供信息。有什么可以帮到您的吗?
# 我是一个人工智能助手,可以帮助您回答问题和提供信息。有什么可以帮到您的吗?

‍以上代码可以是文本回复最没有创造性,接下来做下调整

  temperature=2,
  top_p=0,
我是一个人工智能助手,设计来帮助您回答问题和提供信息。怎么可以帮到您呢?
我是一个人工智能助手,可以提供帮助回答你的问题。有什么可以帮到你的吗?
您好!我是这个平台提供的信息辅助工具。有任何问题不妨问我,我会尽全力帮助您回答问题。
我是一个人工智能助手,可以帮助您回答问题和提供信息。有什么可以帮助您的吗

所以结论就是 :如果需要回答编程,数学,物理问题严谨的对话就需要把temperature数值设置高一些,如果是艺术,创意内容对话可以把temperature设置高一点。

最后

如果觉得内容不错,欢迎点个关注,分享和在看,你的支持是我更新的动力。