欢迎光临
我们一直在努力

大模型应用开发笔记(二)——深入了解OpenAI API

重要模型

  • GPT Base: 针对补全任务训练,不包含对话功能,也未经过RLHF。仅用于预测下一个词元,而非遵循指令。这一系列有babbage-002和davinci-002两个模型,davinci-002参数少但更快。

  • InstructGPT: 是通过大模型应用开发笔记(一)所述的RLHF过程获得的一系列模型,并未针对聊天优化,而是专注于单轮补全任务。

    上述模型已被永久下线,OpenAI建议使用gpt-3.5-turbo-instruct替代这些旧模型,该模型具备gpt-3.5 turbo系列相同的能力,但他兼容传统的 补全接口 而不支持聊天补全。

  • GPT-3.5: 这系列模型专为聊天设计。GPT-3.5 Turbo系列模型的聊天格式旨在支持多轮对话,但同样可以用于单轮补全任务。相较于GPT-4更具成本效益且速度更快。模型通过gpt-3.5-turbo-带面,DDMM表示发布日期。

    OpenAI建议用gpt-4o-mini替代gpt-3.5-turbo,因其性能更强,支持多模态并且速度与后者相当

  • GPT-4: 可以理解复杂的自然语言指令,并准确的解决难题,他们适用于多轮聊天和单轮任务,并具有较高的准确性。GPT-4o支持文本和图像输入。GPT-4o比GPT-4 Turbo更加快速且便宜。

OpenAI Python 库

将API密钥作为环境变量存储

  • 对于Linux或macOS,设置临时环境变量:
  • # 为当前会话设置环境变量 OPENAI_API_KEY
    export OPENAI_API_KEY=sk-(...)
    # 确认环境变量已设置
    echo $OPENAI_API_KEY

  • 对于 Windows可以通过窗口添加环境变量;对于Linux系统,可以将这段代码直接添加到.bashrc 文件中使变量永久。
  • # 为当前会话设置环境变量 OPENAI_API_KEY
    set OPENAI_API_KEY=sk-(...)
    # 确认环境变量已设置
    echo %OPENAI_API_KEY%

  • 在python项目中可以创建一个.env文件并使用dotenv库来使用该环境变量:
  • # .env文件内容:
    OPENAI_API_KEY=sk()
    # python中使用环境变量
    from dotenv import load_dotenv
    load_dotenv()

    使用聊天补全模型

    API不会在上下文中存储之前的消息,每次请求是需要重新把之前所有的对话内容输入,来模拟一个完整的对话。

    from openai import OpenAI
    from dotenv import load_dotenv
    import os

    load_dotenv()

    client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))

    # 对于 GPT-3.5 Turbo,使用的接口是 chat.completions
    response = client.chat.completions.create(
    # 对于 GPT-3.5 Turbo,模型名称是"gpt-3.5-turbo"
    model="gpt-3.5-turbo",
    # 对话以消息列表的形式传递
    messages=[
    {"role": "system", "content": "You are a helpful teacher."},
    {
    "role": "user",
    "content": "Are there other measures than time \\
    complexity for an algorithm?",
    },
    {
    "role": "assistant",
    "content": "Yes, there are other measures besides time \\
    complexity for an algorithm, such as space complexity.",
    },
    {"role": "user", "content": "What is it?"},
    ],
    )
    # 响应打印
    print(response.choices[0].message.content)

    chat.completions.create参数

  • 必须参数
  • 字段名类型描述
    model 字符串 模型ID例如gpt-4o等
    messages 数组 消息参数,表示对话,可包含system、assistant、user、tool消息
  • 消息参数
  • 字段名类型描述
    content 字符串或数组 除了拥有tool_calls数组的assistant消息以外,其他消息必须含有content字段。content消息一般是字符串,但user的content可以包含文本或图像
    role 字符串 指定角色,role的值必须是system、assistant、user、tool之一
    name 字符串 可选,可用于区分对话中的不同角色,可用于system、user、assistant
    tool_calls 数组 仅在assistant消息中,是由模型在先前的API调用中生成的工具调用信息
    tool_calls_id 字符串 仅在tool消息中,属于强制属性

    # user的content可以包含文本或图像,格式如下:
    {"type":"text","text":"Your text here"},
    {"type":"image_url","image_url":"https://yourimageurlhere"}

    对于视觉内容输入会存在不一致的方式:

    "content":[{"type":"image_url","image_url":{"url":your_url}}] # your_url:图像的url
    "content":[{"image":image,"resize":768}] # image:Base64编码的图像

    • system消息有助于设置助手的行为。
    • user消息相当于用户在ChatGPT界面中输入的问题或句子或者设置为指令
    • assistant消息扮演两种角色:存储上下文和设置为指令
  • 其他可选参数
  • 字段名类型描述
    response_format 对象 将参数设置为{“type”: “json_object”},可以强制模型输出JSON。需要注意:必须在messages字段中指定模型生成JSON
    logprobs 布尔值 控制是否返回每个输出词元的 对数概率 。
    tools 数组 可用工具的数组。
    tool_choice 字符串或对象 控制模型的响应方式:

    • none 模型必须以标准方式回应用户;
    • {"type": "function", "function": {"name": "my_function"}}模型必须使用指定函数给出答案
    • auto模型在标准响应和使用tool_choice函数之间选择
    temperature 浮点数(介于0和2.0之间,默认为1.0) temperature为0模型”循规蹈矩“,越大约“放飞自我”更具创意
    top_p 浮点数(默认为1.0) 模型只考虑top-p概率质量的词元,如0.5代表仅考虑总概率大于等于50%的词元
    n 整数(默认为1) 指定生成结果的数量。当输入参数的温度为0时,获得多个非常相似的响应
    seed 整数 它旨在提高结果的可重复性;使用相同的种子进行重复请求时,理论上应返回相同的结果,但不保证完全一致
    stream 布尔值(默认为False) 允许答案以流式形式呈现。当补全内容较长时,可提供更好的用户体验
    max_tokens 整数 在聊天补全中生成的最大词元数量,此参数可选。输入和生成的词元的总长度受到模型词元上限的限制

    Temperature & top_P

    两个参数的作用是在严谨固定与创意多样之间调整平衡。

    Temperature
  • 底层逻辑 大模型生成文本是逐词元预测,基于上下文模型会为下一个出现的所有词元计算对应的概率值,再从词元中选一个作为输出,然后基于新的文本继续预测直到生成结束。
  • temperature=0:极致确定性,只选“最可能”词元。
    • 逻辑:强制选择概率最高的那个次元,完全不考虑其他概率低的词元。
    • 效果:用完全相同的输入多次调用模型,大概率返回完全相同的结果(高度一致)。
  • temperature 越大:随机性越强,创意 / 多样性越高
    • 逻辑:对所有词元的概率做软化处理,给低概率词元一次被选中的机会。
    • 效果:数值越大,软化程度越高,模型越容易 “选到非最高概率的词元”,输出的多样性、创造性就越强,但同时和输入上下文的贴合度会降低。
  • top_P(核采样)

    从概率最高的词元开始累加,直到累加概率达到 topP 的阈值,只从这个 “概率累加池” 里选词元,池外的低概率词元直接抛弃。

    实际调参流程
  • 划定基准线: 设置默认值,比如temperature=0.7, top_p=0.95。
  • 调整核心风格: 保持top_P不变,根据结果调整temperature。
  • 微调质量:
    • 如果偶尔出现奇怪词 → 降低top_P
    • 如果输出太重复/受限 → 提高top_P
  • 总结: temperature调节全局随机性,决定核心风格,top_P调节词汇选择范围,保证输出质量。

    聊天补全模型输出结果格式

    上述模型调用结果如下,下面针对结果进行详细解释:

    ChatCompletion(
    id='chatcmpl-D2fEZkFX681jV96mhLmb2ikT0jieF',
    choices=[Choice(finish_reason='stop',
    index=0,
    logprobs=None,
    message=ChatCompletionMessage(content='Hello! How can I assist you today?',
    refusal=None,
    role='assistant',
    annotations=None,
    audio=None,
    function_call=None,
    tool_calls=None),
    delta={'role': 'assistant', 'content': 'Hello! How can I assist you today?'}
    )],
    created=1769527531,
    model='gpt-4o-mini-2024-07-18',
    object='chat.completion',
    service_tier=None,
    system_fingerprint='fp_f97eff32c5',
    usage=CompletionUsage(completion_tokens=10,
    prompt_tokens=10,
    total_tokens=20,
    completion_tokens_details=CompletionTokensDetails(accepted_prediction_tokens=None,
    audio_tokens=0,
    reasoning_tokens=0,
    rejected_prediction_tokens=None),
    prompt_tokens_details=PromptTokensDetails(audio_tokens=0,
    cached_tokens=0)))

    字段名类型描述
    choices Choice 对象数组 一个包含模型实际响应的数组。默认情况下,该数组只有一个元素,可以通过参数 n 进行更改。该元素包含以下内容:

    • finish_reason(字符串):模型回答完成的原因。 stop意味着收到了模型的完整响应。如果在输出生成过程中出现错误,错误信息将出现在此字段中。
    • index(整数):来自 choices 数组的 Choice 对象的索引。
    • message(对象):role 和 content 或 tool_calls。对于响应role 始终是 assistant,content 包括模型生成的文本。通常我们想获取的是这个字符串:response.choices[0].message.content。
    • logprobs:每个输出词元的对数概率,仅在请求中将 logprobs 设置为 True 时才会生效。
    created 时间戳 生成时时间戳格式的日期。在我们的“Hello World”示例中,这个时间戳可转换为 2023 年 4 月 10 日星期一下午 1:49:55。
    id 字符串 OpenAI 内部使用的技术标识符。
    model 字符串 所使用的模型,与作为输入设置的模型相同。
    object 字符串 对于 GPT-4 和 GPT-3.5 模型,该字段应始终为 chat.completion,因为我们正在使用聊天补全接口。
    usage 对象 token信息:total_tokens = prompt_tokens + completion_tokens。

    视觉能力

    gpt-4-turbo允许向其发送图像,该模型支持PNG、JEPG、WEBP、GIF格式,大小限制为20MB。

    可以在请求中嵌入图像链接:

    from openai import OpenAI
    from dotenv import load_dotenv
    import os

    load_dotenv()

    client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))

    url = """https://upload.wikimedia.org/
    wikipedia/commons/f/f0/Ophiopteris_antipodum.JPG"""

    response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[
    {
    "role": "user",
    "content": [
    {
    "type": "text",
    "text": "Give the name of the animal in the image.",
    },
    {"type": "image_url", "image_url": {"url": url}},
    ],
    }
    ],
    )
    response.choices[0].message.content

    print(response.choices[0].message.content)

    也可以在请求中传递Base64编码的图像:

    from openai import OpenAI
    from dotenv import load_dotenv
    import os

    load_dotenv()

    from base64 import b64encode

    # 将图像转换为Base64格式
    def encode_image(image_path):
    with open(image_path, "rb") as image_file:
    image_data = image_file.read()
    base64_image = b64encode(image_data).decode("utf-8")
    return base64_image

    client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))

    # 具备处理多个图像输入的能力
    base64_image = encode_image("image_1.jpg")
    base64_image = encode_image("image_2.jpg")
    response = client.chat.completions.create(
    model="gpt-4o",
    messages=[
    {
    "role": "user",
    "content": [
    {
    "type": "text",
    "text": "Give the name of the animal in this image.",
    },
    {
    "type": "image_url",
    "image_url": {
    "url": f"data:image/jpeg;base64,{base64_image_1}"
    },
    },
    {
    "type": "image_url",
    "image_url": {
    "url": f"data:image/jpeg;base64,{base64_image_2}"
    },
    },

    ],
    }
    ],
    )

    print(response.choices[0].message.content)

    请求JSON输出

    JSON格式输出

    在将 LLM 功能集成到你的应用程序的过程中,这是一个重要特性:LLM 输出变得可解析,可以用于执行代码。添加response_format参数为{”type“:"json_object"},并在message里指示模型在消息中使用JSON格式输出。

    from openai import OpenAI
    from dotenv import load_dotenv
    import os

    load_dotenv()
    client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))

    response = client.chat.completions.create(
    model="gpt-3.5-turbo-1106",
    response_format={"type": "json_object"},
    messages=[
    {
    "role": "system",
    "content": "Convert the user's query in a JSON object"
    },
    {
    "role": "user",
    "content": "I am looking for blue or red shoes, leather, size 7."
    },
    ],
    )
    print(response.choices[0].message.content)

    返回结果为:

    {
    "color": ["blue", "red"],
    "material": "leather",
    "size": 7
    }

    也可以直接在提示词中添加输出JSON的要求而无须使用response_format参数,但该方案由于模型本身的随机性,长内容、复杂结构下更容易失控,可靠性低。如果必须要这么做,需要把预期的 JSON 字段、类型、示例写清楚,降低模型理解偏差。

    工具与函数

    模型可以在输出中生成调用工具和函数的命令供应用端执行。开发者可以使用函数定义来将自然语言转换为 API 调用或数据库查询,从文本中提取结构化数据,创建调用外部工具回答问题的聊天机器人。

    #mermaid-svg-eyGNhZUsLhtFrQhO{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-eyGNhZUsLhtFrQhO .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-eyGNhZUsLhtFrQhO .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-eyGNhZUsLhtFrQhO .error-icon{fill:#552222;}#mermaid-svg-eyGNhZUsLhtFrQhO .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-eyGNhZUsLhtFrQhO .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-eyGNhZUsLhtFrQhO .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-eyGNhZUsLhtFrQhO .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-eyGNhZUsLhtFrQhO .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-eyGNhZUsLhtFrQhO .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-eyGNhZUsLhtFrQhO .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-eyGNhZUsLhtFrQhO .marker{fill:#333333;stroke:#333333;}#mermaid-svg-eyGNhZUsLhtFrQhO .marker.cross{stroke:#333333;}#mermaid-svg-eyGNhZUsLhtFrQhO svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-eyGNhZUsLhtFrQhO p{margin:0;}#mermaid-svg-eyGNhZUsLhtFrQhO .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-eyGNhZUsLhtFrQhO .cluster-label text{fill:#333;}#mermaid-svg-eyGNhZUsLhtFrQhO .cluster-label span{color:#333;}#mermaid-svg-eyGNhZUsLhtFrQhO .cluster-label span p{background-color:transparent;}#mermaid-svg-eyGNhZUsLhtFrQhO .label text,#mermaid-svg-eyGNhZUsLhtFrQhO span{fill:#333;color:#333;}#mermaid-svg-eyGNhZUsLhtFrQhO .node rect,#mermaid-svg-eyGNhZUsLhtFrQhO .node circle,#mermaid-svg-eyGNhZUsLhtFrQhO .node ellipse,#mermaid-svg-eyGNhZUsLhtFrQhO .node polygon,#mermaid-svg-eyGNhZUsLhtFrQhO .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-eyGNhZUsLhtFrQhO .rough-node .label text,#mermaid-svg-eyGNhZUsLhtFrQhO .node .label text,#mermaid-svg-eyGNhZUsLhtFrQhO .image-shape .label,#mermaid-svg-eyGNhZUsLhtFrQhO .icon-shape .label{text-anchor:middle;}#mermaid-svg-eyGNhZUsLhtFrQhO .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-eyGNhZUsLhtFrQhO .rough-node .label,#mermaid-svg-eyGNhZUsLhtFrQhO .node .label,#mermaid-svg-eyGNhZUsLhtFrQhO .image-shape .label,#mermaid-svg-eyGNhZUsLhtFrQhO .icon-shape .label{text-align:center;}#mermaid-svg-eyGNhZUsLhtFrQhO .node.clickable{cursor:pointer;}#mermaid-svg-eyGNhZUsLhtFrQhO .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-eyGNhZUsLhtFrQhO .arrowheadPath{fill:#333333;}#mermaid-svg-eyGNhZUsLhtFrQhO .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-eyGNhZUsLhtFrQhO .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-eyGNhZUsLhtFrQhO .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-eyGNhZUsLhtFrQhO .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-eyGNhZUsLhtFrQhO .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-eyGNhZUsLhtFrQhO .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-eyGNhZUsLhtFrQhO .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-eyGNhZUsLhtFrQhO .cluster text{fill:#333;}#mermaid-svg-eyGNhZUsLhtFrQhO .cluster span{color:#333;}#mermaid-svg-eyGNhZUsLhtFrQhO div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-eyGNhZUsLhtFrQhO .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-eyGNhZUsLhtFrQhO rect.text{fill:none;stroke-width:0;}#mermaid-svg-eyGNhZUsLhtFrQhO .icon-shape,#mermaid-svg-eyGNhZUsLhtFrQhO .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-eyGNhZUsLhtFrQhO .icon-shape p,#mermaid-svg-eyGNhZUsLhtFrQhO .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-eyGNhZUsLhtFrQhO .icon-shape rect,#mermaid-svg-eyGNhZUsLhtFrQhO .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-eyGNhZUsLhtFrQhO .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-eyGNhZUsLhtFrQhO .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-eyGNhZUsLhtFrQhO :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    用户请求

    LLM分析需求

    是否需要外部工具?

    选择工具+提取参数

    返回结构化调用指令

    应用执行工具

    返回工具结果

    LLM生成最终回答

    在tool参数的数组中定义函数并给到大模型,tool对象有type和function两个属性,目前type值大多是字符串function为主。属性function对象详情如下表所示:

    字段名类型描述
    name 字符串(必需) 函数名称
    description 字符串 对函数的描述
    parameters 对象 该函数的预期参数,这些参数应以JSON Schema格式描述

    下面来做个简单的实践。

  • 定义函数find_product模拟数据库查询操作,
  • 按照上述表格定义该函数的详细信息。
  • 构建messages和tool数组,调用chat.completions。
  • 将响应添加到messages中,响应包含值为assistant的role,tool的id和function内容。
  • 根据响应执行相关操作,得到执行结果。
  • 将执行结果添加到message中,role为tool,tool_call_id要与之前响应的值一致。
  • llm根据qurey和function结果做出回答。
  • 输出结果如下: 输出结果 实践代码如下:

    from openai import OpenAI
    from dotenv import load_dotenv
    import os
    import json

    load_dotenv()
    client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))

    # 示例函数
    def find_product(sql_query):
    # 在此执行查询
    results = [
    {"name": "pen", "color": "blue", "price": 1.99},
    {"name": "pen", "color": "red", "price": 1.78},
    ]
    return results

    # 定义该函数
    function_find_product = {
    "name": "find_product",
    "description": "Get a list of products from a SQL query",
    "parameters": {
    "type": "object",
    "properties": {
    "sql_query": {
    "type": "string",
    "description": "A SQL query",
    }
    },
    "required": ["sql_query"],
    },
    }

    # 创建一个对话并调用chat.completions 接口

    # 示例问题
    user_question = "I need the top 2 products where the price is less \\
    than 2.00"

    messages = [{"role": "user", "content": user_question}]
    # 根据当前函数定义调用 chat.completions 接口
    response = client.chat.completions.create(
    model="gpt-3.5-turbo-1106",
    messages=messages,
    tools=[{"type": "function", "function": function_find_product}])
    response_message = response.choices[0].message
    # print(response.model_dump_json(indent=2))
    # print(response_message.tool_calls[0])

    #——————————API返回的信息——————————-
    # ChatCompletionMessageFunctionToolCall(id='call_sIbBn85cXCYzhlJINCGHSwQs',
    # function=Function(arguments='{"sql_query":"SELECT * FROM products WHERE price < 2.00 ORDER BY price ASC LIMIT 2;"}'
    # ,name='find_product'),
    # type='function',
    # index=0)

    # 添加函数调用响应到 messages 中
    # 这里SDK会自动将返回信息中ChatCompletionMessage对象转换为API需要的字典格式,是官方推荐的最佳实践
    messages.append(response_message)

    # 函数调用

    function_name = response_message.tool_calls[0].function.name

    # function_name = "find_product"
    if function_name == "find_product":
    function_args = json.loads(
    response_message.tool_calls[0].function.arguments
    )
    products = find_product(function_args.get("sql_query"))
    else:
    # 处理错误
    products = []
    # 将函数响应添加到 messages 中
    messages.append(
    {
    "role": "tool",
    "tool_call_id": response_message.tool_calls[0].id,
    "content": json.dumps(products),
    }
    )

    # 将函数响应转换为自然语言

    try:
    # 将函数响应转换为自然语言
    second_response = client.chat.completions.create(
    model="gpt-3.5-turbo-1106",
    messages=messages,
    timeout=30 # 添加超时设置
    )
    print(second_response.choices[0].message.content)
    except Exception as e:
    print(f"=== 错误信息 ===")
    print(f"Error type: {type(e).__name__}")
    print(f"Error message: {str(e)}")

    文本补全接口completions.create的使用

    输入参数:

    字段名类型描述
    model 字符串 要使用的模型
    prompt 字符串或数组 用于生成补全的提示词
    max_tokens 整数 生产的最大词元数
    suffix 字符串 指定生成文本的后缀文本

    代码实践:

    from openai import OpenAI
    client = OpenAI()

    # 调用 openai 库的completions 接口
    response = client.completions.create(
    model="gpt-3.5-turbo-instruct",
    prompt="Hello World!"

    # 输出响应
    print(response.choices[0].text)

    输出结果中choice对象中没有content和role消息,只是一个text文本。

    其他功能

    嵌入(Embedding)

    Embedding通过将文本转换为高维数值向量,把人类语言翻译为模型可以理解的数值语言,Embedding能够保持语义相似性,具有相似含义的单词或短语在数值空间中被映射得更近。OpenAI提供了向量化模型的能力。常见的用法如下:

    用例描述
    搜索 按与查询字符串的相似度对结果进行排序
    推荐 推荐包含与查询字符串相关的文本字符串的文章。
    聚类 按相似度对字符串进行分组。
    异常检测 找到一个与其他字符串无关的文本字符串。

    Embedding的一个典型应用场景是RAG系统,Embedding在 RAG 中用于高效索引庞大的数据集,使得系统能够识别信息,并将最相关的信息整合到一个 LLM 中。

    result = client.embeddings.create(
    model="text-embedding-ada-002",
    input="your input text"

    # 结果是一个embedding
    result.data[0].embedding

    审核

    OpenAI提供了审核模型的接口moderations.create,用于对输入文本进行潜在有害类型的判别与分类。可用参数:模型和输入文本。可选的模型有:text-moderation-latest和text-moderation-stable。

    调用样例:

    from openai import OpenAI
    client = OpenAI()

    # 调用 openai 审核接口的text-moderation-latest 模型
    response = client.moderations.create(
    model="text-moderation-latest",
    input="I want to kill my neighbor."

    返回结果:

    ModerationCreateResponse(
    id='modr-8uoRCpiav9RhVlIvMu0Ppjl6gLmoo',
    model='text-moderation-007',
    results=[
    Moderation(categories=Categories(
    harassment=False,
    harassment_threatening=True,
    hate=False,
    [...]
    sexual_minors=False,
    violence=True,
    violence_graphic=False,
    [...]
    ,
    category_scores=CategoryScores(
    harassment=0.10063749551773071,
    harassment_threatening=0.3250463008880615,
    hate=0.00806125532835722,
    [...]
    sexual_minors=8.04909419116484e-08,
    violence=0.9886732697486877,
    violence_graphic=1.1281177648925222e-05,
    [...]
    ,
    flagged=True]

    输出描述:

    字段名类型描述
    model 字符串 模型名称
    flagged 布尔值 如果内容违反了OpenAI政策值为True,否则为False
    categories 对象 包含分类信息的字典,可通过response.results[0].categories来访问
    category_scores 对象 表示各个类别的评分,可通过response.results[0].category_scores来访问
    文本转语音

    OpenAI 提供了一个带有 TTS 模型的音频API。目前 OpenAI 有两个可用 TTS 模型:tts-1 和 tts-1-hd。tts-1 是标准模型,经过优化以提高速度,但其质量低于另一个模型。输出可以为mp3、opus、aac、flac格式。以下是其使用示例:

    import json
    from openai import OpenAI
    from dotenv import load_dotenv
    import os

    load_dotenv()
    client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"),
    base_url="https://api.chatanywhere.tech/v1")

    response = client.audio.speech.create(
    model="tts-1",
    voice="alloy",
    input="I won't be home tonight. Could you please take the dog \\
    for a walk?"
    )

    # 方式A:使用 .content(字节数据)
    with open("output.mp3", "wb") as f:
    f.write(response.content)

    # 方式B:使用 .read()(等效)
    # with open("output.mp3", "wb") as f:
    # f.write(response.read())

    输入参数:

    字段名类型描述
    model 字符串(必需) 模型名称
    input 字符串(必需) 用于生成音频的文本。最大长度为4096字符
    voice 字符串 以下值之一:alloy,echo,fable,onyx,nova,shimmer
    response_format 字符串(默认为mp3) 以下值之一:mp3,opus,aac,flac
    speed 浮点数(默认为1.0) 生成音频的速度,取值范围为0.25-4.0
    语音转文本

    Whisper是一个多功能的语音识别模型,可执行多语言语音转录文本和翻译。接受多种音频格式: flac、m4a、mp3、mp4、mpeg、mpga、ogg、wav 和 webm。

    ASR

    from openai import OpenAI
    client = OpenAI()

    transcript = client.audio.transcriptions.create(
    model="whisper-1",
    file=open("speech.mp3", "rb")

    transcript.text

    可以使用提示词来提高Whisper API的转录质量:

    from openai import OpenAI
    client = OpenAI()

    transcript = client.audio.transcriptions.create(
    model="whisper-1",
    file=open("speech.mp3", "rb"),
    prompt="This is a description of a painting done by Salvador Dalí."

    transcript.text

    另一种方案是将Whisper的转录内容提供给LLM进行后处理:

    response = client.chat.completions.create(
    model="gpt-4",
    messages=[
    {
    "role": "system",
    "content": """Your task is to correct any spelling
    mistakes in the text. The text is about a description
    of a painting done by Salvador Dalí."""

    },
    {
    "role": "user",
    "content": transcript.text
    }
    ]

    response.choices[0].message.content

    输入参数:

    字段名类型描述
    file 文件对象(必需) 音频文件,支持类型:flac、m4a、mp3、mp4、mpeg、mpga、ogg、wav、webm
    model 字符串(必需) 模型名称
    language 字符串 语言
    prompt 字符串 音频上下文或指定风格
    response_format 字符串(默认为json) 输出文本的格式,支持类型:json、text、srt、verbose_json、vtt
    temperature 浮点数(默认为0) 采样温度
    翻译

    Whisper可以自动检测输入的语言,将任务语言的音频数据翻译为英语文本,需要用到audio.translations接口,其参数与audio.transcriptions相比只少了language字段。我们先使用TTS创建一个音频文件:

    from openai import OpenAI
    client = OpenAI()

    response = client.audio.speech.create(
    model="tts-1",
    voice="echo",
    input="Les mathématiques sont une science fondamentale."

    response.stream_to_file("speech_fr.mp3")

    对生成的音频文件进行翻译转录便得到英文文本结果:

    from openai import OpenAI
    client = OpenAI()

    transcript = client.audio.translations.create(
    model="whisper-1",
    file=open("speech_fr.mp3", "rb")
    )
    transcript.text

    图像API

    DALL·E是OpenAI推出的文生图模型,可执行文生图,图像编辑与图生图等任务。E3版本相较于E2,允许输入的提示词更多,生成分辨率更高,但一次仅可请求一张图像,E2可批量最多生成10张,当然我们也可以通过并发请求获取更多的DALL·E3图像。

    1. 图像生成

    发送请求后会接收到response.data[0].url是指向生成图像的url,还会接收到revised_prompt,是模型为你重写的提示词。提示词重写无法禁用但可以在提示词中加入“不要添加任何细节,只需按原样使用”等字样来鼓励模型保持你的文本。相关实践如下:

    from openai import OpenAI
    from dotenv import load_dotenv
    import os
    import json
    load_dotenv()
    client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))

    response = client.images.generate(
    model="dall-e-3",
    prompt="An image with a cute spiny brittle star with distinct arms.",
    n=1,
    size="1024×1024",
    quality="hd"
    )

    print(response.data[0].url)

    输入参数为:

    字段名类型描述
    prompt 字符串(必需) 提示词。对于 DALL·E 2 和 DALL·E 3,分别可以包含最多 1000 和 4000 个字符。
    model 字符串(默认为 dall-e-2) 模型名称,必须为 dall-e-2 或 dall-e-3。
    n 整数(默认为 1) 生成图像的数量。对于 DALL·E 2,必须在 1 和 10 之间;对于 DALL·E 3,必须为 1。
    quality 字符串(默认为 standard) 生成图像的质量。hd 表示在整个图像中产生更细致和一致的细节。仅 DALL·E 3 支持。
    response_format 字符串(默认为 url) 指定生成的图像以 url 或 b64_json 格式返回。
    style 字符串(默认为 vivid) DALL·E 3 的图像风格选项。有两个可用的值:vivid 和 natural。vivid 会创建超现实和戏剧性的图像,而 natural 则会创建更自然的图像。
    user 字符串 一个独特的标识符,代表你的终端用户,并可以帮助 OpenAI 监控和检测滥用行为。

    如果指定response_format参数为b64_json,则将数据编码为Base64字符串且包装在JSON对象中返回,我们可以将字符串解码为二进制数据并保存到本地:

    from base64 import b64decode
    image_bytes = b64decode(response.data[0].b64_json)
    with open("decoded_image.png", "wb") as image_file:
    image_file.write(image_bytes)

    知识补充

    模式用途适用场景
    r 文本模式读取(默认) 读取SQL脚本、配置文件.txt
    rb 二进制模式读取 读取图片、压缩包.zip
    w 文本模式写入(覆盖) 写入日志、文本格式数据
    wb 二进制模式写入(覆盖) 写入图片、音频、二进制数据
    a 文本模式追加 追加日志文件
    ab 二进制模式追加 追加二进制数据文件
    2. 图像编辑

    需要准备原始图像和与原始图像相同但带有蒙版的图像,蒙版中的透明区域指示了图像需要修改的位置。两张必须是都小于4MB且具有相同尺寸的正方形PNG图像。

    from openai import OpenAI
    client = OpenAI()

    response = client.images.edit(
    model="dall-e-2",
    image=open("img-star.png", "rb"),
    mask=open("img-star_alpha.png", "rb"),
    prompt="""An image with a cute spiny brittle star with distinct
    arms and with a cute smiling face in the center."""
    ,
    n=1,
    size="1024×1024"

    image_url = response.data[0].url

    输入参数为:

    字段名类型描述
    image 文件对象(必需) 要编辑的图像文件对象(而非文件名)。如果未指定蒙版,则图像必须具有透明度才能用作蒙版
    prompt 字符串(必需) 描述所需图像的文本,最多支持 1000 个字符
    mask 文件对象 带有透明区域的附加图像,以指示需要编辑的区域
    model 字符串(默认为 dall-e-2) 用于编辑图像的模型。目前,仅支持 dall-e-2
    n 整数(默认为 1) 生成图像的数量,必须在 1 和 10 之间
    size 字符串 生成图像的大小,必须是以下值之一:256×256、512×512、1024×1024(单位为像素)
    response_format 字符串(默认为 url) 指定生成的图像以 url 或 b64_json 格式返回
    user 字符串 一个独特的标识符,代表你的终端用户,并可以帮助 OpenAI 监控和检测滥用行为
    3. 图像变体

    该API允许你生成特定图像的不同版本。

    from openai import OpenAI
    client = OpenAI()

    response = client.images.create_variation(
    image=open("img-star_edit.png", "rb"),
    size="1024×1024"

    response.data[0].url

    输入参数为:

    字段名类型描述
    image 文件对象(必需) 用于变体的基础图像必须是有效的 PNG 文件,应小于 4 MB,并且是正方形
    model 字符串(默认为 dall-e-2) 生成图像所使用的模型。目前,仅支持 dall-e-2
    n 整数(默认为 1) 生成的图像数量,必须在 1 和 10 之间
    size 字符串 生成图像的大小,必须是以下值之一:256×256、512×512、1024×1024(单位为像素)
    response_format 字符串(默认为 url) 指定生成的图像以 url 或 b64_json 格式返回
    user 字符串 一个独特的标识符,代表你的终端用户,并可以帮助 OpenAI 监控和检测滥用行为
    赞(0)
    未经允许不得转载:171主机测评 » 大模型应用开发笔记(二)——深入了解OpenAI API
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址