【LangChain系列】9. 实用技巧:大模型的流式输出在 OpenAI 和 LangChain 中的使用

当大模型的返回文字非常多时,返回完整的结果会耗费比较长的时间。如果等待大模型形成完整的答案再展示给用户,明显会给用户不好的体验。所以,现在市面上大多数的AI应用,在给用户结果时,都是以流式输出的方式展示给用户的。所谓的流式输出,就是类似打字机式的方式,一个字或一个词的输出,给用户一种答案逐渐出现的动画效果。

今天我们来学习下如何流式输出大模型的返回结果。本文将涵盖 LangChain 的流式输出方式和 OpenAI 原生的流式输出方式。
在这里插入图片描述

0. LangChain的流式输出 Streaming

0.1 实现流式输出

我们在 【AI大模型应用开发】【LangChain系列】实战案例4:再战RAG问答,提取在线网页数据,并返回生成答案的来源 代码的基础上,增加流式输出。

原代码:

python代码解读复制代码import bs4
from langchain import hub
from langchain_community.document_loaders import WebBaseLoader
from langchain_community.vectorstores import Chroma
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter

# Load, chunk and index the contents of the blog.
loader = WebBaseLoader(
    web_paths=("https://lilianweng.github.io/posts/2023-06-23-agent/",),
    bs_kwargs=dict(
        parse_only=bs4.SoupStrainer(
            class_=("post-content", "post-title", "post-header")
        )
    ),
)
docs = loader.load()

text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(docs)
vectorstore = Chroma.from_documents(documents=splits, embedding=OpenAIEmbeddings())

# Retrieve and generate using the relevant snippets of the blog.
retriever = vectorstore.as_retriever()
prompt = hub.pull("rlm/rag-prompt")
llm = ChatOpenAI(model_name=<
LangChain 中实现 DeepSeek API 的流式输出功能,可以通过重写 `_stream` 方法,手动接入 HTTP 流响应,从而实现逐步获取生成结果的能力。LangChain 默认采用同步方式返回模型输出结果,而 DeepSeek 提供了标准的 `stream=True` 接口,允许以流式方式逐步接收响应内容 [^4]。 为了实现流式输出,需要在 LangChain 中创建一个自定义类,继承 `ChatOpenAI` 或 `ChatDeepSeek` 类,并重写 `_stream` 方法。该方法应返回一个生成器(generator),逐块读取 DeepSeek API 的响应内容,并通过 `yield` 逐步返回每个 token 的文本内容 [^4]。 以下是一个示例代码,展示了如何在 LangChain 中实现 DeepSeek 的流式输出: ```python from langchain_openai import ChatOpenAI from langchain_core.messages import HumanMessage, SystemMessage import requests class DeepSeekStreamChat(ChatOpenAI): def _stream(self, prompt, stop=None, run_manager=None, **kwargs): # 构造请求参数 headers = { "Authorization": f"Bearer {self.openai_api_key}", "Content-Type": "application/json" } data = { "model": self.model_name, "prompt": prompt, "stream": True } # 发起流式请求 with requests.post(self.openai_api_base, headers=headers, json=data, stream=True) as response: for line in response.iter_lines(): if line: decoded_line = line.decode("utf-8") if decoded_line.startswith("data: "): content = decoded_line[6:] # 解析 content 字段并提取生成的 token yield {"text": content} # 初始化自定义的流式 Chat 模型 llm = DeepSeekStreamChat( model_name="deepseek-chat", openai_api_key="YOUR_API_KEY", openai_api_base="https://api.deepseek.com/v1", temperature=0.8, max_tokens=1024 ) # 定义对话消息 messages = [ SystemMessage(content="Translate the following English text to Chinese"), HumanMessage(content="Hello, how are you?") ] # 流式输出每个 token for token in llm.stream(messages): print(token["text"], end="", flush=True) ``` 在实际开发中,还需要确保 `openai_api_base` 指向 DeepSeek 的 API 地址 `https://api.deepseek.com/v1`,并且 `model_name` 设置为 `deepseek-chat` 或其他支持流式输出的模型 [^3]。 此外,还可以利用 `Tool` 类 `initialize_agent` 创建一个代理,通过 DeepSeek API 实现流式生成任务。例如,可以定义一个 `deepseek_tool` 函数,将其封装为 `Tool` 实例,并通过 `initialize_agent` 创建代理来执行流式输出任务 [^2]。 在流式输出模式下,从 DeepSeek API 接收到的数据是以 JSON 格式的分块(chunk)传输的,每个 chunk 包含了部分响应数据。这些数据通常位于 `choices[0].delta.content` 字段中,可以通过解析每个 chunk 提取生成的文本片段 [^1]。 为了判断 DeepSeek API 的响应是否已经完成,可以检查 `finish_reason` 字段的值。如果 `finish_reason` 为 `null`,表示还有更多的数据将要发送;如果为 `stop` 或其他非空值,则表示生成过程已经完成 [^1]。 最后,需要注意的是,使用流式输出时,应当合理设置 `temperature` `max_tokens` 等参数,以控制生成结果的多样性长度。同时,还需处理可能的错误异常情况,确保程序的健壮性用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值