小白的AIGC课(2)— 上下文提问与流式输出

让我们回顾一下上一节课的代码:

import anthropic
import os

my_api_key = os.environ.get("ANTHROPIC_API_KEY")

client = anthropic.Anthropic(
    # defaults to os.environ.get("ANTHROPIC_API_KEY")
    api_key=my_api_key,
)

message = client.messages.create(
    model="claude-3-opus-20240229",
    max_tokens=1000,
    temperature=0.0,    
    messages=[
        {"role": "user", "content": "How are you today?"}
    ]
)

print(message.content)

在这个代码里,我们作为用户向大模型提了一个问题”How are you today?”,实际使用中,用户的提问是连续的,并且要求大模型可以根据上下文进行回答,那应该如何做到这一点呢?

下面是修改后的代码:

import anthropic
import os

my_api_key = os.environ.get("ANTHROPIC_API_KEY")
client = anthropic.Anthropic(api_key=my_api_key)

system_message = "You are Claude, an AI assistant."

print("Welcome! Type 'exit' to end the conversation.")

conversation = []

while True:
    user_input = input("You: ")
    if user_input.lower() == "exit":
        break

    conversation.append({"role": "user", "content": user_input})

    message = client.messages.create(
        model="claude-3-opus-20240229",
        max_tokens=1000,
        temperature=0.0,
        system=system_message,
        messages=conversation
    )

    conversation.append({"role": "assistant", "content": message.content})
    response_text = "".join(block.text for block in message.content)
    print("Claude:", response_text)

在这段代码中,我们增加了一个while循环,记录用户的输入,直到用户输入exit时才退出循环。

同时建立一个新的列表变量conversation[],用来储存上下文,将用户的提问和AI模型的回答存储在这个变量中,并作为参数传递到message实例中,最后为了显示效果,新建了一个response_text的变量用来获取message.content中的文本部分。如果直接显示message.content会出现如下格式,对用户不是很友好。

[ContentBlock(text=”Ansower from AI model”, type=’text’)]

同时注意到在参数中加入了一个system的参数,这个参数的作用是指导AI模型遵循某个角色,在这里是一个AI助手的角色,这样它的输出就会遵循某种格式和规则。

下面我们来测试一下改动后代码的效果,问题是跟老板提加薪。

可以看出新的代码可以进行连续提问和理解上下文。

还有一个问题是有如果回答比较长,或者大模型的处理时间比较久,有时候等待答案输出就需要花一段时间,这个时候streaming(流式输出)功能就很有用了, 可以将答案一个字一个字地蹦出来。我们来看下如何实现这个streaming功能。

import anthropic
import os

my_api_key = os.environ.get("ANTHROPIC_API_KEY")
client = anthropic.Anthropic(api_key=my_api_key)

conversation = []

while True:
    user_input = input("You: ")
    if user_input.lower() == "exit":
        break

    conversation.append({"role": "user", "content": user_input})

    with client.messages.stream(
        model="claude-3-opus-20240229",
        max_tokens=1000,
        temperature=0.0,        
        messages=conversation
    ) as stream:        
        response_text = ""
        for text in stream.text_stream:
            response_text += text
            print(text, end="", flush=True)

    conversation.append({"role": "assistant", "content": text})
    print()

以下是这段代码的不同之处:

我们不使用 client.messages.create(…),而是使用 client.messages.stream(…),它返回一个流对象。我们将流包装在 with 语句中以确保正确的资源处理。在 with 块内,我们初始化一个空字符串 response_text = “”。然后我们迭代stream.text_stream,它会在可用时以块的形式生成响应文本。

对于每个文本块,我们:

将其附加到response_text 字符串。

使用 print(text, end=””,lush=True) 打印文本块。end=”” 确保打印块时不带换行符,flush=True 强制立即打印输出而无需缓冲。

流式传输完成后,我们将完整的response_text附加到对话列表中。

在完全打印响应后,我们打印换行符 print() ,以分隔下一个提示。

使用此代码,您应该会看到 AI 的响应在生成时实时打印,一次打印一大块。这对于您想要在生成响应时显示响应而不是等待整个响应准备就绪的应用程序非常有用。

请注意,与非流式传输方法相比,流式传输响应可能会导致输出略有不同,因为文本是以块的形式生成和传输的。但总体意义和内容应该是相同的。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注