OpenAI GPT For Python Developers 第四章 使用GPT编辑文本

发布于 2023年10月15日

在给定提示和一组指令之后,您正在使用的GPT模型将采用提示,然后使用其算法生成原始提示的修改版本。

这个修改后的版本可能比初始提示更长和/或更详细,具体取决于您的指令。

GPT模型能够理解提示和给定的指令的上下文,从而确定在输出中包含哪些附加细节会最有益处。

示例:翻译文本

我们始终使用相同的开发环境,名为“chatgptforpythondevelopers”。首先激活它:

workon chatgptforpythondevelopers

请注意,“.env”文件应始终存在于包含Python文件的当前目录中。

现在创建包含以下代码的“app.py”文件:

import os
import openai

def init_api():
    with open(".env") as env:
        for line in env:
            key, value = line.strip().split("=")
            os.environ[key] = value

    openai.api_key = os.environ.get("API_KEY")
    openai.organization = os.environ.get("ORG_ID")

init_api()

response = openai.Edit.create(
    model="text-davinci-edit-001",
    input="Hallo Welt",
    instruction="Translate to English",
)

print(response)

在上面的代码中,我们使用相同的函数进行身份验证:

import os
import openai

def init_api():
    with open(".env") as env:
        for line in env:
            key, value = line.strip().split("=")
            os.environ[key] = value

    openai.api_key = os.environ.get("API_KEY")
    openai.organization = os.environ.get("ORG_ID")

init_api()

然后,我们要求API将德语文本翻译成英语:

response = openai.Edit.create(
    model="text-davinci-edit-001",
    input="Hallo Welt",
    instruction="Translate to English",
)

print(response)

执行上述代码后,您应该看到以下输出:

{
  "choices": [{
   "index": 0,
   "text": "Hello World!\n"
  }],
  "created": 1674653013, 
  "object": "edit", 
  "usage": {"completion_tokens": 18, "prompt_tokens": 20, "total_tokens": 38} 
}

API返回了一个单一的选择,索引为0,如上述输出中所示。与Completion不同,在完成中我们提供API一个提示,但在这里我们需要提供指令和输入。

指令是必需的,而输入是可选的。

可以只提供指令并在同一行中包含输入:

import os
import openai

def init_api():
    with open(".env") as env:
        for line in env:
            key, value = line.strip().split("=")
            os.environ[key] = value

    openai.api_key = os.environ.get("API_KEY")
    openai.organization = os.environ.get("ORG_ID")

init_api()

response = openai.Edit.create(
    model="text-davinci-edit-001",
    instruction="Translate the following sentence to English: 'Hallo Welt'",
)

print(response)

使用Edit和Completion Endpoint进行编辑

一些可以使用编辑Endpoint执行的任务也可以使用补全Endpoint完成。取决于您的需求,您可以选择使用哪种方法。

以下是使用编辑Endpoint执行翻译任务的示例:

import os
import openai

def init_api():
    with open(".env") as env:
        for line in env:
            key, value = line.strip().split("=")
            os.environ[key] = value

    openai.api_key = os.environ.get("API_KEY")
    openai.organization = os.environ.get("ORG_ID")

init_api()

response = openai.Edit.create(
    model="text-davinci-edit-001",
    instruction="Translate from English to French, Arabic, and Spanish.",
    input="The cat sat on the mat."
)

print(response)

这与上述任务相同,但使用了补全Endpoint:

import os 
import openai

def init_api():
    with open(".env") as env:
        for line in env:
            key, value = line.strip().split("=")
            os.environ[key] = value

    openai.api_key = os.environ.get("API_KEY")
    openai.organization = os.environ.get("ORG_ID")

init_api()

next = openai.Completion.create(
    model="text-davinci-003",
    prompt="""
    Translate the following sentence from English to French, Arabic, and Spanish.
    English: The cat sat on the mat.
    French:
    Arabic:
    Spanish:
    """,
    max_tokens=60,
    temperature=0
)

print(next)

另一方面,以下示例将使用编辑Endpoint执行文本补全任务:

import os
import openai

def init_api():
    with open(".env") as env:
        for line in env:
            key, value = line.strip().split("=")
            os.environ[key] = value

    openai.api_key = os.environ.get("API_KEY")
    openai.organization = os.environ.get("ORG_ID")

init_api()

response = openai.Edit.create(
    model="text-davinci-edit-001",
    instruction="Complete the story",
    input="Once upon a time",
)

print(response['choices'][0]['text'])

格式化输出

让我们看看这个示例:我们要求编辑端点为Golang代码添加注释。

import os
import openai

def init_api():
    with open(".env") as env:
        for line in env:
            key, value = line.strip().split("=")
            os.environ[key] = value

    openai.api_key = os.environ.get("API_KEY")
    openai.organization = os.environ.get("ORG_ID")

init_api()

response = openai.Edit.create(
    model="text-davinci-edit-001",
    instruction="Explain the following Golang code:",
    input="""
    package main
    import (
        "io/ioutil"
        "log"
        "net/http"
    )
    func main(){
       
       resp, err := http.Get("https://website.com") 
       if err != nil { 
         log.Fatalln(err) 
       
       } 
       
       body, err := ioutil.ReadAll(resp.Body) 
	   if err != nil {
         log.Fatalln(err)
       }
       
       sb := string(body)
       log:Printf(sb)
   }
    """
)

print(response['choices'][0]['text'])

输出将不可读:

{
 "choices": [{
"index": 0,
"text": "\npackage main\n\nimport (\n\t// code to work with input and output\n\ \t\"io/ioutil\"\n\n\t//codetoworkwithlogging\n\t\"log\"\n\n\t//codetoworkwi\ th http\n\t\"net/http\"\n)\n\nfunc main() {\n resp, err := http.Get(\"https://website.com\")\n   if err != nil {\n      log.Fatalln(err)\n   }\n\n
il.ReadAll(resp.Body)\n   if err != nil {\n      log.Fatalln(err)\n body, err := iout\
string(body)\n   log.Printf(sb)\n}  \n  \n"
} ],
"created": 1674765343, 
"object": "edit", 
"usage": {
  "completion_tokens": 467, 
  "prompt_tokens": 162, 
  "total_tokens": 629
} 
}

然而,如果只打印文本,它应该格式正确:

import os
import openai

[..same code..]

print(response["choices"][0]["text"])

这是上面代码的输出:

//MainFile-this will connect to the webpagge,download the file and print out contents
packagemain
import(
//Import io for string and log for any problems I may have with connection "io/ioutil"
"log"
"net/http"
)

func main(){
     //http.Get will connect to the provided webpage
     resp, err := http.Get("https://website.com")
     if err != nil {
      log.Fatalln(err)
     }

      //once webpagge is connected body, err will download the webpage
      body, err := ioutil.ReadAll(resp.Body) 
      if err != nil {
        log.Fatalln(err)
        //once I have the body of the webpage then body, err will download the webpage
      }

   //once download is finished, sb will print out the contents of the website
   sb := string(body)
   log.Printf(sb)

}

创造力与明确定义的答案

与补全Endpoint一样,我们可以使用温度参数控制结果的创造力。

您可以尝试使用两个不同的温度值来运行以下示例,以查看输出的差异:

import os
import openai

def init_api():
    with open(".env") as env:
        for line in env:
            key, value = line.strip().split("=")
            os.environ[key] = value

    openai.api_key = os.environ.get("API_KEY")
    openai.organization = os.environ.get("ORG_ID")

init_api()

response_1 = openai.Edit.create(
    model="text-davinci-edit-001",
    instruction="correct the spelling mistakes:",
    input="The kuick brown fox jumps over the lazy dog and",
    temperature=0,
)

response_2 = openai.Edit.create(
    model="text-davinci-edit-001",
    instruction="correct the spelling mistakes:",
    input="The kuick brown fox jumps over the lazy dog and",
    temperature=0.9,
)

print("Temperature 0:")
print(response_1['choices'][0]['text'])
print("Temperature 0.9:")
print(response_2['choices'][0]['text'])

通常,在多次运行代码后,您可能会观察到第一个输出是一致的,而第二个输出在不同次执行中会发生变化。对于纠正拼写错误之类的用例,我们通常不需要创造性,因此将温度参数设置为0就足够了。

如果有其他用例,但不是这个用例,创造性参数应该设置为大于0。以下是一个可以更具创造性的机会:

import os
import openai

def init_api():
    with open(".env") as env:
        for line in env:
            key, value = line.strip().split("=")
            os.environ[key] = value

    openai.api_key = os.environ.get("API_KEY")
    openai.organization = os.environ.get("ORG_ID")

init_api()

response = openai.Edit.create(
    model="text-davinci-edit-001",
    input="Exercise is good for your health.",
    instruction="Edit the text to make it longer.",
    temperature=0.9,
)

print(response["choices"][0]["text"])

以下是一个输出示例:

Exercise is good for your health.Especially if you haven't done any for a month.

这是另一种输出变体:

Exercise is good for your health. 

It will help you improve your health and mood. 

It is important for integrating your mindand body.

另一种获取更具创造性的方式是使用top_p参数。

这是与温度一起进行采样的替代方法,因此建议不要同时使用温度和top_p:

import os
import openai

def init_api():
    with open(".env") as env:
        for line in env:
            key, value = line.strip().split("=")
            os.environ[key] = value

    openai.api_key = os.environ.get("API_KEY")
    openai.organization = os.environ.get("ORG_ID")

init_api()

response = openai.Edit.create(
    model="text-davinci-edit-001",
    input="Exercise is good for your health.",
    instruction="Edit the text to make it longer.",
    top_p=0.1,

)

print(response["choices"][0]["text"])

在上述示例中,我使用了top_p=0.1,这意味着模型将考虑具有top_p概率质量=0.1的标记的结果。换句话说,结果中只考虑前10%概率质量的标记。

生成多个编辑

在以前的所有示例中,我们总是只有一个编辑。然而,使用参数n,可以获得更多编辑。只需使用您想要的编辑数量:

import os
import openai

def init_api():
    with open(".env") as env:
        for line in env:
            key, value = line.strip().split("=")
            os.environ[key] = value

    openai.api_key = os.environ.get("API_KEY")
    openai.organization = os.environ.get("ORG_ID")

init_api()

response = openai.Edit.create(
    model="text-davinci-edit-001",
    input="Exercise is good for your health.",
    instruction="Edit the text to make it longer.",
    top_p=0.2,
    n=2,
)

print(response["choices"][0]["text"])
print(response["choices"][1]["text"])

在上述示例中,我使用了n=2来获取两个结果。

我还使用了top_p=0.2。然而,这与结果数量无关;我只是想拥有更广泛范围的结果。

高级文本操作示例

到目前为止,我们已经看到了如何使用不同的端点:edits和completions。让我们做更多的示例,以了解模型提供的不同可能性。

链式的Completion与Edit

在此示例中,我们将要求模型从文本中生成一条推文,然后将其翻译成另一种语言。

在第一个任务中,我们将使用完成端点获取推文文本,然后是第二个任务的代码,用于翻译推文:

import os
import openai

def init_api():
    with open(".env") as env:
        for line in env:
            key, value = line.strip().split("=")
            os.environ[key] = value

    openai.api_key = os.environ.get("API_KEY")
    openai.organization = os.environ.get("ORG_ID")

init_api()

prompt = "The first programming language to be invented was Plankalkül, which was designed by Konrad Zuse in the 1940s, but not publicly known until 1972 (and not implemented until 1998). The first widely known and successful high-level programming language was Fortran, developed from 1954 to 1957 by a team of IBM researchers led by John Backus. The success of FORTRAN led to the formation of a committee of scientists to develop a universal computer language; the result of their effort was ALGOL 58. Separately, John McCarthy of MIT developed Lisp, the first language with origins in academia to be successful. With the success of these initial efforts, programming languages became an active topic of research in the 1960s and beyond\n\nTweet with hashtags:"

english_tweet = openai.Completion.create(
    model="text-davinci-002",
    prompt=prompt,
    temperature=0.5,
    max_tokens=20,
)

english_tweet_text = english_tweet["choices"][0]["text"].strip()
print("English Tweet:")
print(english_tweet_text)

spanish_tweet = openai.Edit.create(
    model="text-davinci-edit-001",
    input=english_tweet_text,
    instruction="Translate to Spanish",
    temperature=0.5,
)

spanish_tweet_text = spanish_tweet["choices"][0]["text"].strip()
print("Spanish Tweet:")
print(spanish_tweet_text)

通过执行上面的代码,我们可以看到两个不同语言的推文:

英文推文:The#first#programming#languagetobeinventedwas#Plankalkül

西班牙文推文:Elprimerlenguajedeprogramacióninventadofue#Plankalkül

请注意,我们添加了strip()以删除前导和尾随空格。

Apple公司与水果苹果(上下文填充)

让我们创建一个代码,告诉我们一个词是名词还是形容词。在这方面的挑战之一是,当我们向模型提供词汇表时,可以看到这一点,比如“light”。"Light"可以是名词、形容词或动词。

- The light is red.

- This desk is very light.

- You light up my life.

还有其他可以同时用作名词、形容词或动词的词汇:比如 "firm", "fast", "well"等等,这个示例也适用于它们。

现在,如果我们想要询问模型,我们可以编写以下代码:

prompt = "Determine the part of speech of the word 'light'.\n\n"
result = openai.Completion.create(
    model="text-davinci-002",
    prompt=prompt,
    max_tokens=20,
    temperature=1,
)

print(result.choices[0]["text"].strip())

您可以尝试此代码,它有时会输出动词,有时形容词,有时名词,但我也得到了以下结果:单词 'light' 可以用作名词、形容词或动词。

通过使用上下文,我们可以影响模型的响应。上下文是向模型提供的提示,用于指导其通过用户定义的模式。

让我们在提供一些提示的同时询问模型。提示可以是任何有助于模型理解上下文的内容。

例如:

prompt_a = "The light is red. Determine the part of speech of the word 'light'.\n\n"
prompt_b = "This desk is very light. Determine the part of speech of the word 'light'.\n\n"
prompt_c = "You light up my life. Determine the part of speech of the word 'light'.\n\n"

for prompt in [prompt_a, prompt_b, prompt_c]:
    result = openai.Completion.create(
        model="text-davinci-002",
        prompt=prompt,
        max_tokens=20,
        temperature=0,
    )

    print(result.choices[0]["text"].strip())

更好地理解上下文会导致以下结果:

noun

adjective

verb

另一个示例是下面这个,我们向模型提供了两个不同的提示。在第一种情况下,我们希望模型理解Apple是一家公司,而在第二种情况下,Apple应该指的是水果。

prompt = "Huawei:\ncompany\n\nGoogle:\ncompany\n\nMicrosoft:\ncompany\n\nApple:\n"
prompt += "Huawei:\ncompany\n\nGoogle:\ncompany\n\nMicrosoft:\ncompany\n\nApricot:\nFruit\n\nApple:\n"

result = openai.Completion.create(
    model="text-davinci-002",
    prompt=prompt,
    max_tokens=20,
    temperature=0,
    stop=["\n", " "],
)

print(result.choices[0]["text"].strip())

基于用户定义的Schema获取加密货币信息(上下文填充)

让我们看看第二个示例,其中我们提供了模型应在输出中遵循的架构或模板。

我们的目标是获取有关给定加密货币的一些信息,包括其简称、创建日期、其Coingecko页面以及历史最高和历史最低价。

import os
import openai

def init_api():
    with open(".env") as env:
        for line in env:
            key, value = line.strip().split("=")
            os.environ[key] = value

    openai.api_key = os.environ.get("API_KEY")
    openai.organization = os.environ.get("ORG_ID")

init_api()

prompt = """
Input: Bitcoin
Output:
BTC was created in 2008, you can learn more about it here: https://bitcoin.org/en/ and get the latest price here: https://www.coingecko.com/en/coins/bitcoin.
It's all-time high is $64,895.00 and it's all-time low is $67.81.
Input: Ethereum
Output:
ETH was created in 2015, you can learn more about it here: https://ethereum.org/en/ and get the latest price here: https://www.coingecko.com/en/coins/ethereum.
It's all-time high is $4,379.00 and it's all-time low is $0.43.
Input: Dogecoin
Output:
DOGE was created in 2013, you can learn more about it here: https://dogecoin.com/ and get the latest price here: https://www.coingecko.com/en/coins/dogecoin.
It's all-time high is $0.73 and it's all-time low is $0.000002.
Input: Cardano
Output:

"""

result = openai.Completion.create(
    model="text-davinci-002",
    prompt=prompt,
    max_tokens=200,
    temperature=0,
)

print(result.choices[0]["text"].strip())

我们首先提供模型应返回的示例:

Input: BTC was created in 2008, you can learn more about it here: https://bitcoin.org/en/ and get the latest price here: https://www.coingecko.com/en/coins/bitcoin. It's all-time high is $64,895.00 and it's all-time low is $67.81.

Input: Ethereum

Output:

ETH was created in 2015, you can learn more about it here: https://ethereum.org/en/ and get the latest price here: https://www.coingecko.com/en/coins/ethereum. It's all-time high is $4,379.00 and it's all-time low is $0.43.

Input: Dogecoin

Output:

DOGE was created in 2013, you can learn more about it here: https://dogecoin.com/ and get the latest price here: https://www.coingecko.com/en/coins/dogecoin. It's all-time high is $0.73 and it's all-time low is $0.000002.

然后我们调用端点。您可以根据需要更改输出格式。例如,如果需要HTML输出,可以在答案中添加HTML标记。

例如:

Input: Bitcoin

Output:

BTC was created in 2008, you can learn more about it <a href="https://bitcoin.org/en/">here</a> and get the latest price <a href="https://www.coingecko.com/en/coins/bitcoin">here</a>.

It's all-time high is $64,895.00 and it's all-time low is $67.81.

模型将返回类似的输出。

创建一个用于处理Linux命令的聊天助手

免责声明:本部分受到OpenAI 2020年的一个旧演示的启发。

我们的目标是开发一个可以通过对话来帮助我们处理Linux命令的命令行工具。

让我们从以下示例开始:

import os
import openai

def init_api():
    with open(".env") as env:
        for line in env:
            key, value = line.strip().split("=")
            os.environ[key] = value

    openai.api_key = os.environ.get("API_KEY")
    openai.organization = os.environ.get("ORG_ID")

init_api()

prompt = """
Input: List all the files in the current directory
Output: ls -l

Input: List all the files in the current directory, including hidden

 files

Output: ls -la

Input: Delete all the files in the current directory

Output: rm *

Input: Count the number of occurrences of the word "sun" in the file "test.txt"

Output: grep -o "sun" test.txt | wc -l

Input: {}

Output: 
"""

result = openai.Completion.create(
    model="text-davinci-002",
    prompt=prompt.format("Count the number of files in the current directory"),
    max_tokens=200,
    temperature=0,
)

print(result.choices[0]["text"].strip())

我们需要模型的单一响应,这就是为什么我们使用了空温度。我们提供了足够的令牌来处理输出。

模型提供的答案应为:

ls -l | wc -l

我们将使用click21(CLI创建工具包),这是一个用最少的代码创建命令行界面的Python包。这将使我们的程序更加互动。

首先,在激活虚拟开发环境后,通过以下方式安装Python包:

workon chatgptforpythondevelopers

pip install click==8.1.3

然后,让我们创建一个名为`app.py`的文件:

import os
import openai
import click

def init_api():
    with open(".env") as env:
        for line in env:
            key, value = line.strip().split("=")
            os.environ[key] = value

    openai.api_key = os.environ.get("API_KEY")
    openai.organization = os.environ.get("ORG_ID")

init_api()

_prompt = """

Input: List all the files in the current directory

Output: ls -l

Input: List all the files in the current directory, including hidden files

Output: ls -la

Input: Delete all the files in the current directory

Output: rm *

Input: Count the number of occurrences of the word "sun" in the file "test.txt"

Output: grep -o "sun" test.txt | wc -l

Input: {}

Output: 

"""

while True:
    request = input(click.style("Input", fg="green"))
    prompt = _prompt.format(request)
    result = openai.Completion.create(
        model="text-davinci-002",
        prompt=prompt,
        temperature=0.0,
        max_tokens=100,
        stop=["\n"],
    )

    command = result.choices[0].text.strip()
    click.echo(click.style("Output: ", fg="yellow") + command)
    click.echo()

我们使用相同的提示。唯一的更改是将click添加到无限循环内的代码。当执行`app.py`时,我们的程序将要求输出(请求),然后将其插入提示并传递给API。

在程序结束时,click会打印结果。最后的`click.echo()`将打印一个空行。

$ python app.py

Input: list all

Output: ls

Input: delete all

Output: rm -r *

Input: count all files

Output: ls -l | wc -l

Input: count all directories

Output: find . -type d | wc -l

Input: count all files that are not directories

Output: find . ! -type d | wc -l

让我们实现一个退出命令:

import os
import openai
import click

def init_api():
    with open(".env") as env:
        for line in env:
            key, value = line.strip().split("=")
            os.environ[key] = value

    openai.api_key = os.environ.get("API_KEY")
    openai.organization = os.environ.get("ORG_ID")

init_api()

_prompt = """

Input: List all the files in the current directory

Output: ls -l

Input: List all the files in the current directory, including hidden files

Output: ls -la

Input: Delete all the files in the current directory

Output: rm *

Input: Count the number of occurrences of the word "sun" in the file "test.txt"

Output: grep -o "sun" test.txt | wc -l

Input: {}

Output: 

"""

while True:
    request = input(click.style("Input (type 'exit' to quit): ", fg="green"))
    prompt = _prompt.format(request)
    if request == "exit":
        break
    result = openai.Completion.create(
        model="text-davinci-002",
        prompt=prompt,
        temperature=0.0,
        max_tokens=100,
        stop=["\n"],
    )

    command = result.choices[0].text.strip()
    click.echo(click.style("Output: ", fg="yellow") + command)
    click.echo()

最后,让我们实现一个执行生成的命令的指令:

import os
import openai
import click

def init_api():
    with open(".env") as env:
        for line in env:
            key, value = line.strip().split("=")
            os.environ[key] = value

    openai.api_key = os.environ.get("API_KEY")
    openai.organization = os.environ.get("ORG_ID")

init_api()

_prompt = """

Input: List all the files in the current directory

Output: ls -l

Input: List all the files in the current directory, including hidden files

Output: ls -la

Input: Delete all the files in the current directory

Output: rm *

Input: Count the number of occurrences of the word "sun" in the file "test.txt"

Output: grep -o "sun" test.txt | wc -l

Input: {}

Output: 

"""

while True:
    request = input(click.style("Input (type 'exit' to quit): ", fg="green"))
    if request == "exit":
        break

    prompt = _prompt.format(request)

    try:
        result = openai.Completion.create(
            model="text-davinci-002",
            prompt=prompt,
            temperature=0.0,
            max_tokens=100,
            stop=["\n"],
        )

        command = result.choices[0].text.strip()
        click.echo(click.style("Output: ", fg="yellow") + command)
        click.echo(click.style("Execute? (y/n): ", fg="yellow"), nl=False)
        choice = input()

        if choice == "y":
            os.system(command)
        elif choice == "n":
            continue
        else:
            click.echo(click.style("Invalid choice. Please enter 'y' or 'n'.", fg="red"))
    except Exception as e:
        click.echo(click.style("The command could not be executed. {}".format(e), fg="red"))
        pass

    click.echo()

```



评论