OpenAI API返回单词片段而非完整词,如何获取完整词及概率?
解决OpenAI API返回单词片段的问题
问题原因
GPT系列模型采用**字节对编码(BPE)**机制,长单词会被拆分为多个小token(比如broccoli会拆成"bro"和"ccoli")。当你只获取第一个生成的token时,自然会得到不完整的单词片段。
解决方案
1. 调整聊天接口调用,强制生成完整单词
修改prompt明确要求输出单个完整单词,并设置stop参数为空格(或换行),让模型生成到空格就停止;同时设置足够的max_tokens覆盖最长可能的单词。最后将生成的所有token拼接为完整单词,并计算联合概率(所有token的logprob之和的指数)。
修改后的代码示例:
from openai import OpenAI from math import exp import numpy as np import os client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY", "<your OpenAI API key if not set as env var>")) def get_completion( messages: list[dict[str, str]], model: str = "gpt-4", max_tokens=10, temperature=0, stop=None, seed=123, logprobs=True, top_logprobs=3, ) -> object: params = { "model": model, "messages": messages, "max_tokens": max_tokens, "temperature": temperature, "stop": stop, "seed": seed, "logprobs": logprobs, "top_logprobs": top_logprobs, } completion = client.chat.completions.create(**params) return completion sentence_list = [ "Yesterday I went to the", "My least favorite food is" ] results = [] for sentence in sentence_list: # 明确要求输出单个完整单词 PROMPT = f"Output only one complete word to finish this sentence: {sentence}" API_RESPONSE = get_completion( [{"role": "user", "content": PROMPT}], stop=" ", # 遇到空格停止生成 model="gpt-4" ) # 拼接所有token为完整单词 full_word = "".join([token.token for token in API_RESPONSE.choices[0].logprobs.content]) # 计算完整单词的联合概率 total_logprob = sum([token.logprob for token in API_RESPONSE.choices[0].logprobs.content]) probability = float(np.round(exp(total_logprob)*100, 2)) results.append([sentence, full_word, total_logprob, probability])
2. 使用补全接口(Completions API)替代聊天接口
补全接口更适合续写类任务,能更精准控制生成单个完整单词。目前GPT-4暂不支持补全接口,可选用gpt-3.5-turbo-instruct等模型。
代码示例:
def get_completion_completions( prompt: str, model: str = "gpt-3.5-turbo-instruct", max_tokens=10, temperature=0, stop=" ", seed=123, logprobs=5, ) -> object: params = { "model": model, "prompt": prompt, "max_tokens": max_tokens, "temperature": temperature, "stop": stop, "seed": seed, "logprobs": logprobs, } completion = client.completions.create(**params) return completion sentence_list = [ "Yesterday I went to the", "My least favorite food is" ] results = [] for sentence in sentence_list: PROMPT = f"{sentence}" API_RESPONSE = get_completion_completions( PROMPT, stop=" ", model="gpt-3.5-turbo-instruct" ) # 获取完整单词 full_word = API_RESPONSE.choices[0].text.strip() # 计算联合概率 total_logprob = sum(API_RESPONSE.choices[0].logprobs.token_logprobs) probability = float(np.round(exp(total_logprob)*100, 2)) results.append([sentence, full_word, total_logprob, probability])
3. 手动拼接BPE token获取top3完整单词候选
如果必须用聊天接口且需要top3完整单词,需编写逻辑遍历每个token的top候选,拼接成可能的完整单词,计算每个单词的总logprob(组成token的logprob之和)后排序取top3。核心思路:
- 用字典存储候选单词及其总logprob
- 迭代拼接token候选,直到遇到空格或达到最大token数
- 按总logprob排序后提取top3
注意事项
- GPT-4聊天接口仅返回单个token的候选,无法直接获取完整单词的top候选,需手动处理;补全接口更适配这类场景。
- 设置
temperature=0会让模型返回最确定的结果,有助于获取稳定的完整单词。
内容的提问来源于stack exchange,提问作者Clau alv
相关产品推荐
相关产品推荐

