ChatGpt的api使用入门
liduoan.efls Engineer

一、前言

两周前已经介绍了ChatGpt的相关账号注册、apiKey的获取,以及关键的Prompt提示语。

而在知晓了如何注册、如何通过引导语获得我们想要的回答之后,本文将介绍如何使用openai的一些接口,让我们能够使用现有的AI接口来构建一些应用和工具。

image

二、API介绍

openapi官网:OpenAI API

官方doc文档:https://platform.openai.com/docs/introduction

OpenAI API 几乎可以应用于任何涉及理解或生成自然语言、代码或图像的任务。

其提供一系列具有不同功率级别的模型,适用于不同的任务,这些模型可用于从内容生成到语义搜索和分类的所有领域。

1、名词解释

Token:

openai的模型是通过将文本分解为名为token的较小单元来处理文本。token可以是单词,单词块或单个字符。

通过下面的文本来举例,其是如何被分解为token的: I have an orange cat named Butterscotch. 常见的单词,如“cat”,是一个单独的token,而不常用的单词通常会分解为多个token。例如,“Butterscotch”会转换为四个token:“But”、“ters”、“cot”和“ch”。

当前gpt-3.5-turbo计费价格为1000token/0.002美元

Temperature

temperature是一种超参数,在一些自然语言处理模型中被使用,包括ChatGPT,用于控制生成文本中的随机性或“创造性”水平。

简而言之,温度越低,结果就越确定,因为模型将始终选择最可能的下一个token。增加温度可能会导致更多的随机性,从而鼓励更多样化或创造性的输出。我们实际上是增加了其他可能token的权重。

在应用方面,我们可能希望对于基于事实的问答等任务使用较低的温度值,以鼓励更加事实和简洁的回答。对于生成诗歌或其他创意任务,增加温度值可能会更有益。

image

有兴趣可以在文档中拖动temperature尝试 https://platform.openai.com/docs/quickstart/adjust-your-settings

image

Top_p

top_p 是 OpenAI GPT 系列模型中的一个参数,用于控制生成文本的多样性。

通过调整 top_p 的值,可以控制生成文本的多样性。较小的 top_p 值会导致生成文本较为保守,而较大的 top_p 值会导致生成文本更加自由和多样化。

通常,建议在调整 top_p 值时,将其设置在 0.1 到 0.9 的范围内,一般改变top_p或Temperature,但不是两者兼而有之。

2、Api的简单使用

1、直接发起请求

platform.openai.com

既然是RESTful的请求,当然可以直接按照http的格式发起请求

官网中的实例如下:

1
2
3
4
5
6
7
curl https://api.openai.com/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer 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" \
-d '{
"model": "gpt-3.5-turbo",
"messages": [{"role": "user", "content": "Hello!"}]
}'

一般我们在网页上使用chatGpt直接就传入一段prompt就完了,但是api中有所不同。

api的入参从一段 Prompt 变成了一个数组,数组的每个元素都有 role 和 content 两个字段。

role 这个字段一共有三个参数可以选择,分别是

  • user 代表用户
  • assistant 代表 AI 的回答。
  • system 代表系统,其content里的内容代表我们给 AI 的一个指令,也就是告诉 AI 应该怎么回答用户的问题
  1. 当 role 是 user 或者 assistant 的时候,content 里面的内容就代表用户和 AI 对话的内容。

发起请求,得到对应的返回值:

image

2、使用openai封装的库

openai官方提供了python、node.js的脚本库,此外其他开源爱好者也提供了各类语言的sdk接入方式。

例如go的接入方式:https://github.com/sashabaranov/go-openai

这里主要以Python为例,简要的使用python完成调用

其必要的东西是:

  • Openai的python库
    • pip install openai
  • openai的key
1
2
3
4
5
6
7
8
9
10
11
12
13
import openai

openai.api_key = "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"

response = openai.ChatCompletion.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?"}
]
)

三、基于python+ChatGpt构建一个听懂人话的命令行工具

1、需求介绍

制作一个能够听懂人话的工具,我们表达想要完成的内容,它能够告诉我们应该怎么去写对应的命令

例如下面的创建5个txt文件,名字类似,我们不需要写完整所有的内容,ai就能够告知我们最终的是什么命令:

image

需求分析:

1、能够使用cgpt xxx就可以执行

2、能够理解文本的内容转化成mac可执行的命令

3、能够按下enter运行,同时输入任意命令可以不执行

4、终端上的输出相对美观

2、使用cgpt xxx就可以执行对应脚本

实质上就是将python文件变为mac的执行脚本文件,直接问!

Prompt:

我有一个名为cgpt的python命令行工具的脚本,我想将这个脚本变为mac上的可执行脚本文件 这样我打开终端,无论在任何位置直接输入cgpt命令,就可以运行这个python脚本

image

2、构建可用的prompt

理解文本的内容转化成mac可执行的命令,这一步是整个工具的关键能力。

而「转化文本内容并只输出对应的命令」,其实质就是构建一个能够满足我们需求的****prompt

prompt调试的工具可以使用:

platform.openai.com

a、你是mac电脑专家

image

我们希望输出的命令行是正确的,不需要ai的输出有创造性和多样性,所以在右边设置了其Temperature和Top P都为0。

在完成设置之后,可以看到在上述promot下,其输出含有大量的解释,和预期的输出不一致。

可以增加限制和举例,让ai能够理解我们的诉求,输出我们想要的东西。

b、举例和增加限制

image

如此我们就通过增加限制和简单的举例,得到了想要的输出。

最终的prompt为:

你是一个mac电脑专家,能够把自然语言翻译成在mac上命令行语句。

另外你要遵循下面的几条规则:

1、简单地输出翻译后的指令,不需要做任何说明或解释。

2、如果你不理解我在说什么或者不确定如何将我的指令转换成计算机命令行,简单地输出7个字母“UNKNOWN”。

3、如果翻译结果包含多行命令,请使用“&”或“&&”将它们组合成一行命令。

#USER

翻墙

#ASSISTANT

UNKNOWN

3、编写python脚本

对于python也没有非常的熟悉,直接上手去写一个命令行工具可能需要一定的时间去查阅各类库包等等。

对此,直接咨询chatgpt好了。

a、Basic Prompt Framework

查阅了关于 ChatGPT prompt 的框架资料,这里使用的是Elavis Saravia 总结的框架,他认为一个 prompt 里需包含以下几个元素:

  • Instruction(必须): 指令,即你希望模型执行的具体任务。
  • Context(选填): 背景信息,或者说是上下文信息,这可以引导模型做出更好的反应。
  • Input Data(选填): 输入数据,告知模型需要处理的数据。
  • Output Indicator(选填): 输出指示器,告知模型我们要输出的类型或格式。

只要你按照这个框架写 prompt ,模型返回的结果都不会差。

当然,你在写 prompt 的时候,并不一定要包含所有4个元素,而是可以根据自己的需求排列组合,一般使用Instruction + Context + Input Data就可以

b、python脚本对应的prompt

我希望创建一个python命令行工具脚本,它的名字为cligpt

这个python脚本在mac上运行,例如我在mac终端上执行:

python3 cligpt 查看当前所有文件

脚本会将「查看当前所有文件」认为是一个输入值,他会将这个输入值给chatgpt的api,api会返回一个mac上的可执行的命令并显示在终端上,如其返回了:

ls

这时我按下enter键就可以执行这个命令,另外输入非enter键就不会执行这个文件

输入上述的prompt就可以得到下面的脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#!/usr/bin/env python3

import openai_secret_manager
import openai
import argparse
import sys
import subprocess

# 连接到OpenAI API
openai.api_key = "api_key"

# 定义解析器
parser = argparse.ArgumentParser(description="CLI for running terminal commands using OpenAI's GPT language model")

# 添加参数
parser.add_argument("command", help="The command to run in the terminal", nargs="+")

# 解析参数
args = parser.parse_args()

# 将命令组合成一个字符串
command = " ".join(args.command)

# 使用OpenAI GPT-3 API生成命令
response = openai.Completion.create(
engine="davinci-codex",
prompt=f"Given the following command-line input, generate the corresponding command:\n\n{command}\n\nCommand:",
temperature=0.5,
max_tokens=2048,
)

# 获取API返回的生成的命令
generated_command = response.choices[0].text.strip()

# 在终端中打印生成的命令
print(f"Generated command: {generated_command}")

# 如果用户按下回车,则执行生成的命令
if input("Press enter to run the command, or any other key to cancel...") == "":
subprocess.run(generated_command, shell=True)

这个脚本能够初步满足我们的要求,但是还有以下的问题存在:

1、脚本中chatgpt的模型为davinci-codex,不是chat-gpt3.5

2、脚本的执行太粗糙,终端上的显示效果不够美观

c、优化样式及修改model

我们让chatgpt优化及美化脚本

imageimage

imageimage

之后我将模型和对应上文设计好的prompt放入脚本之中

最终的产物如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import click
import subprocess
from rich.console import Console
from questionary import confirm
from typing import Optional
import openai

openai.api_key = "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"

# Call OpenAI GPT-3 API to get command based on user input
def generate_command(user_input: str) -> str:
# 使用OpenAI GPT-3 API生成命令
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": """
你是一个命令行翻译程序。你可以将自然语言指令从人类语言翻译成mac上相应的命令行语句。
1、简单地输出翻译后的指令,不需要做任何解释。
2、如果你不理解我在说什么或者不确定如何将我的指令转换成计算机命令行,简单地输出7个字母“UNKNOWN”,不做其他解释。
3、如果翻译结果包含多行命令,请使用“&”或“&&”将它们组合成一行命令。
# USER
查看当前文件
# ASSISTANT
cat
"""},
{"role": "user", "content": user_input}
],
temperature = 0
)

# 获取API返回的生成的命令
return response['choices'][0]['message']['content']

@click.command()
@click.argument("user_input")
@click.option(
"--dry-run", is_flag=True, help="Display the generated command but don't run it."
)
def main(user_input: str, dry_run: bool):
# Generate command based on user input
generated_command = generate_command(user_input)

# Print formatted output
console = Console()
console.print(f"[bold green]User input:[/bold green] {user_input}")
console.print(f"[bold green]Generated command:[/bold green] {generated_command}")

# Prompt user to execute command
if not dry_run and confirm("Do you want to execute this command?").ask():
try:
subprocess.run(
[generated_command],
shell=True
)
except subprocess.CalledProcessError as e:
console.print(
f"[bold red]Command execution failed with exit code {e.returncode}[/bold red]"
)
if verbose:
console.print(
f"[bold red]Standard output:[/bold red] {e.stdout.decode('utf-8').strip()}"
)
console.print(
f"[bold red]Standard error:[/bold red] {e.stderr.decode('utf-8').strip()}"
)
else:
console.print("[bold green]Command executed successfully.[/bold green]")
elif dry_run:
console.print(
"[bold cyan]Dry run mode activated. Command not executed.[/bold cyan]"
)
else:
console.print("[bold yellow]Command execution canceled.[/bold yellow]")

if __name__ == "__main__":
main()

四、总结

基于openai的接口,我们能够完成以往相对困难的nlp处理,同时也大大简化了书写脚本的复杂度。

上文的实践Demo中,我们主要是使用了prompt工程和chatgpt3.5的Api接口,同时利用简单的prompt描述框架,快速的得到我们想要的信息,和api组合在一起,我们就得到一个稳定可用的工具。

openai提供的模型远不止chat一种,还有语音、图片等相关的api,可以组合或者单一使用这些api来构建一些有趣的应用。

业务上的可能性

搭建基于知识库内容的机器人 | Learning Prompt

此外针对xxxxx的大量oncall,也可以尝试编写一个较好的prompt接入chatgpt的api来完成相关的oncall,预期可以降低oncall的数量~。下面是一个简单的举例:

prompt:

你是个专注且严谨的问答专家,你需要理解清楚上下文并尽可能按上下文如实的回答问题,如果你不知道或不确定,就只回答:你不知道。不要多输出。

上下文:

[ xxxxxxxxxxxxxxxxxxx

]

【图片】

准确的上下文和准确的答案是息息相关的,但是openai的参数限制最大的 token 数是 4096,大约是 16000 多个字符,也就是说我们没有办法导入很多的上下文给到ai。

现有的解决这个限制的思路是:我们仅需要传符合你咨询的信息的上下文的给 AI,然后 AI 仅用该上下文来生成答案。

目前现有的是使用ChatIndex来帮助:A Primer to using LlamaIndex ‒ LlamaIndex documentation

image

GPTIndex 这个库简单理解就是做上图左边的那个部分,它的工作原理是这这样的:

  1. 创建文档索引
  2. 找到最相关的索引
  3. 最后将对应索引的内容作为上下文给 GPT-3

参考资料

参考资料