Skip to content

Commit

Permalink
blog: add flow use case (#1070)
Browse files Browse the repository at this point in the history
  • Loading branch information
GuangmingLuo committed May 8, 2024
1 parent dff8f17 commit 8e384a0
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 1 deletion.
5 changes: 5 additions & 0 deletions content/zh/cooperation/_index.md
Expand Up @@ -60,6 +60,11 @@ CloudWeGo 关注真实企业用户落地,构建企业用户支持体系和维
<a href='{{< relref "foundersc" >}}'>了解更多</a>
{{< /card >}}

{{< card header="Kitex Thrift Streaming 在字节跳动 Prompt 平台的实践" img="/img/usedby/bytedance.png">}}
字节跳动 Prompt 平台借助 Kitex 的 Thrift streaming 能力,成功实现了流式接口的落地,从而为用户提供了流畅、高效的打字机效果大模型结果输出体验。<br/><br/>
<a href='{{< relref "flow" >}}'>了解更多</a>
{{< /card >}}

{{< /cardpane >}}

</div>
Expand Down
147 changes: 147 additions & 0 deletions content/zh/cooperation/flow.md
@@ -0,0 +1,147 @@
---
type: docs
title: "Kitex Thrift Streaming 在 Prompt 平台的实践"
linkTitle: "字节跳动-Flow"
weight: 8
---

> 本文根据2024年3月30日在北京举办的“云原生✖️AI时代的微服务架构与技术实践”CloudWeGo技术沙龙北京站活动字节跳动-Flow 研发工程师杜少丰的演讲《Kitex Thrift Streaming 在 AI 场景落地实践》整理而来。
## 概述

字节跳动 Prompt 平台旨在为用户提供全面的 Prompt 开发、调优、评测及应用等全生命周期功能。在这些功能中,打字机效果的流式输出大模型结果是一项至关重要的特性。
基于 SSE(Server-Sent Events)实现虽然可行,但需要额外编写 HTTP 服务,这增加了开发的复杂性。而轮询方式虽然简单,但用户体验并不理想,显得过于笨拙。
至于 gRPC,虽然性能出色,但可能引入兼容性问题,使得部署和维护变得复杂。因此,我们借助 [Kitex][Kitex] 的 Thrift streaming 能力,成功实现了流式接口的落地,从而为用户提供了流畅、高效的打字机效果大模型结果输出体验。

## 业务背景

随着 AI 技术的不断发展,人们的生活正在发生深刻的变化。以字节旗下的 AI 产品豆包为例,其中的智能体给人们带来了许多新奇的体验。
其中,AI男友、AI女友等趣味智能机器人尤其受欢迎,它们不仅能够以风趣幽默的方式与用户互动,还能展现出温柔体贴的一面。

这一切都离不开一个与大模型紧密相连的概念——提示词(Prompt)。简单来说,Prompt 就是向预训练模型输入的文本,用以引导模型生成符合特定需求的文本输出。
形象地讲,Prompt 就像是为大模型打造一个专属的梦境,通过它,我们能够引导大模型在特定场景下给出更贴切、更有针对性的回答。

以AI女友为例,我们会通过精心设计的 Prompt 来告诉大模型,它的角色是一个温柔体贴的虚拟女友。同时,我们还会设定一些限制条件,比如要求它以温柔体贴的方式与用户交流,并具备倾听、理解、鼓励和建议等技能。
此外,我们还会详细描述它的工作流程,比如在问候时引导用户说出自己的名字,为用户起一个合适的昵称,然后与用户进行深入的沟通交流,并提供有益的建议。

通过这样的 Prompt,我们为大模型构建了一个完整的“梦境”,让它明白自己是一个AI女友,并清楚自己应该如何与用户互动。
当这个 Prompt 被激活后,我们与大模型进行问答时,它就会根据我们的提示给出相应的回复。比如,当我们向它问好时,它会引导我们说出自己的名字,并为我们取一个可爱的昵称,然后给予我们鼓励和宽慰。

从这个例子中可以看出,Prompt 在特定场景下对大模型的输出起着决定性的作用。更进一步地说,它还会影响到大模型在输出过程中 token 的消耗以及响应时间的快慢。因此,一个优秀的 Prompt 对于提升模型输出效果至关重要。

## 需求场景

字节跳动 Flow 团队正致力于构建一个全面而成熟的平台/方法,旨在帮助 Prompt 开发者设计、迭代、评测及优化其Prompt,从而增强 LLM(大型语言模型)的表现力。
在开发阶段,我们计划提供结构化生成和引导式生成的方式,以辅助用户编写出高效且精准的 Prompt,并进行相应的调试运行。

随着开发的深入,我们将进一步引入 COT(Chain of Thought)、Few shots 等自动调优技术,以及 APO(Auto Prompt Optimization)方法,帮助 Prompt 提高回答的正确率。
同时,我们还将提供 Prompt 扩缩写的能力,以优化大模型在 token 消耗方面的效率。

此外,为了全面评估 Prompt 的效果,我们将结合多样化的数据集对 Prompt 进行打分,并深入分析其性能瓶颈,以便进行针对性的改进。
最终,我们将提供一键部署的功能,使开发者能够轻松地将 Prompt 能力及其背后的大模型集成到他们的应用中。

![flow_platform](/img/users/flow/flow1.png)

当然,这些功能的实现都离不开对实时流式传输技术的支持。就像你体验过的GPT、豆包、百度AI搜索等AI能力一样,它们在用户提问后,都采用了打字机形式的回复方式,
让用户感受到数据在不断流入屏幕,从而提高了聊天的流畅性和响应速度。这种实时流式传输技术正是我们 Prompt 平台需要提供的最基础能力。
通过将数据分成多个数据流进行网络传输,我们可以有效减少网络延迟,提高性能,确保用户在与大型语言模型交互时获得更好的体验。

## 解决方案

为了实现流式输出功能,我们进行了深入的调研,综合考虑了多种方案:

- 轮询
- HTTP SSE
- Kitex gRPC Streaming(protobuf)
- Kitex Thrift Streaming

首先,轮询方案由于其呆板性,不符合我们的需求,因此被排除在外。其次,虽然基于 HTTP 的 SSE 是一种可行的方案,但考虑到我们对 RPC(远程过程调用)同样有严格的要求,因此也需要寻找更为合适的方案。
另外,我们发现 Protobuf 协议的流式处理支持并不能完全满足我们的需求,尤其是在 Thrift 接口方面。最后,我们注意到了 [Kitex][Kitex] 对于 Thrift Streaming 的支持。
当时,Kitex Thrift Streaming 正处于开发阶段,我们果断决定成为其首批用户,并以此为基础构建整个 Prompt 平台的基本框架。

![basic_framework](/img/users/flow/flow2.png)

在架构设计上,我们首先对标 LangChain,建立 LLM 工程化服务。在此基础上,我们进一步构建 Prompt 服务,以提供最基本的 Prompt 管理及应用能力。
为了与前端进行交互,我们通过 API Gateway 提供 HTTP 接口。而在微服务之间的通信方面,我们采用了 Kitex 框架,以提供流式接口和非流式接口的支持,确保数据的高效传输和处理。

通过这一解决方案,我们成功实现了流式输出功能,为用户提供了更加流畅、高效的AI交互体验。同时,我们也为未来的扩展和优化打下了坚实的基础。

## 实践与踩坑

### 流式调用

流式调用的流程起始于用户发起提问。这一请求首先被发送至网关,网关随后与下游的 Prompt RPC 接口建立连接。Prompt RPC 接口进一步与 LLM 工程化服务建立通信,
该服务负责持续与模型交互,并获取模型的输出结果。这些结果通过流式的方式逐层向上传递,直至到达网关层,并最终实现流式上屏展示给用户。

在此过程中,我们在 Prompt 服务中编写了一个流式接口,用于处理流式调用。该接口首先通过调用下游接口建立与下游的连接,然后通过一个 for 循环不断地去接收下游吐给我们的这个流式的包的结果。
一旦接收到数据包,我们通过 send 方法将其向上层透传,直至遇到错误或流关闭为止,循环随之结束。

在实现过程中,我们体验到了 Kitex Thrift Streaming 的简洁性。然而,我们也遇到了一些问题。尤其是在错误处理方面,我们发现代码运行时无法获取预期结果,甚至导致 CPU 负载过高。

![error_handle](/img/users/flow/flow3.png)

进一步分析错误日志后,我们发现在单个请求中存在错误信息,特别是关于首包的 QPM(查询每秒)超限问题。按照我们的代码逻辑,遇到这类错误应该快速退出 for 循环,但实际情况并非如此。
于是,我们开始利用 Kitex 提供的排查手段进行问题定位。Kitex 提供了 RPCStart 和 RPCEnd 的埋点,以及更细粒度的包接收和发送事件埋点。
通过对这些埋点的分析,我们发现 Kitex 将整个请求识别为正常响应,并且在调用链路上有大量的数据包在发送。进一步查看单个包的打点信息,也显示被 Kitex 识别为正常响应。

经过初步判断,我们认为 Kitex 的流式处理中可能忽略了业务错误,导致错误未被正确识别。与 Kitex 团队沟通后,他们进行了相应的调整,例如在代码中增加了对 biz status error(业务状态错误)的识别。

基于这次错误处理的经验,我们进一步分析了流式调用中可能遇到的其他异常场景,如建联阶段的权限报错、首包阶段的 TPM/QPM 超限、中间包阶段的流超时以及内容审核错误等。
我们重点关注了 Kitex Thrift Streaming 在这些场景下的错误处理表现,如建联时是否能快速返回错误信息,以及在首包和中间包返回错误时是否能迅速停止流等待。经过与 Kitex 团队的共同调整和测试,最终这些场景下的错误处理均符合预期。

### 服务治理

在服务治理方面,我们特别关注超时和限流两个关键环节。

![service_governance](/img/users/flow/flow4.png)

首先,超时管理至关重要。由于我们的模块与大模型进行交互,这种交互可能涉及秒级甚至分钟级的响应时间。因此,在 HTTP 层和 RPC 层,
我们都对流处理设置了分钟级的超时限制。这样做可以避免因无法退出for循环而导致的服务阻塞,确保服务的稳定性和可用性。

在限流方面,虽然 Kitex 支持在创建流时进行限流,但对于 LLM 场景来说,我们的关注点不仅在于建立连接时的 QPM 限流,更在于大模型 token 消耗的限流。
大模型的推理过程中会产生大量的 token 消耗,如果不加以限制,可能会导致资源耗尽和服务崩溃。
因此,我们利用 Kitex 实现了建联的限流,同时借助自己的分布式组件来计算不同模型下的 token 消耗,并据此实现 token 级别的限流。这样做可以有效地控制资源使用,避免服务过载。

然而,我们也对 Kitex 抱有期待。我们希望未来 Kitex 能够提供包粒度上的自定义限流能力。这样,我们可以更灵活地定义限流规则,更精确地控制资源使用,从而进一步提升服务的稳定性和性能。

## 未来的期待

随着AI技术的不断发展和应用,我们对微服务框架在AI场景下的能力有着更高的期待。特别是在便捷性、AI场景下的能力以及传统框架能力的适配等方面,我们希望能够看到更多的创新和进步。

### 便捷性

首先,在便捷性方面,我们**期待微服务框架能够支持更多的测试工具接入**,尤其是针对流式接口的测试。目前,对于Kitex Thrift streaming 接口的测试还存在一定的局限性,
主要依赖于编写非流式接口进行包装调用。未来,我们希望能够通过泛化调用等方式,使得流式接口能够更方便地支持各种测试工具,提高开发效率。

### 2. AI场景下的能力

随着AI技术的蓬勃发展,越来越多的产品开始融入AI能力以优化用户体验和功能。在AI场景下,我们对微服务框架如 Kitex 提出了更高的期待,期望它能更好地支持AI组件的集成与编排,以及适配传统的框架能力。

- 开箱即用的 AI 组件编排能力

在当前的开发实践中,当需要集成AI能力时,开发人员通常需要自行处理复杂的逻辑,如调用 prompt、解析大模型输出、以及将结果转换为机器语言等。
这不仅增加了开发难度,也降低了开发效率。因此,我们期待 Kitex 框架能够提供开箱即用的AI组件编排能力。

具体来说,我们期望框架能够预置一系列封装好的AI组件,如 prompt 组件、大模型组件、结果解析组件以及RPC调用组件等。
这些组件应该具备高度的可配置性和可扩展性,以便能够适应不同的业务需求。开发人员只需将业务逻辑传入这些组件,而无需关心组件内部的实现细节,从而能够更专注于业务逻辑的实现。

- 灵活的 AI 组件编排能力

除了提供预置的AI组件外,我们还期待 Kitex 框架能够支持灵活的AI组件编排能力。这意味着框架应该提供一种表达式语言或可视化工具,使得开发人员能够轻松地按照业务需求编排这些AI组件。
通过这种方式,开发人员可以定义组件之间的执行顺序、通信方式以及并行处理策略等,而无需深入了解组件之间的交互细节。这将大大提高AI应用的开发效率和可维护性。

- 传统框架能力在 LLM 链路上适配

在AI场景下,传统的框架能力如**服务治理、元数据透传以及可观测性**等仍然具有重要意义。因此,我们期待Kitex框架能够在这些方面做出适配和优化。

首先,在服务治理方面,由于AI应用可能涉及长时间的推理过程,因此框架需要提供针对秒级甚至分钟级响应时间的超时和限流策略。同时,还需要考虑如何处理与AI组件相关的异常情况。

其次,在元数据透传方面,我们期望框架能够支持在AI组件之间传递元数据,以便进行更精细化的监控和调试。这将有助于我们更好地理解AI应用的运行状况,并快速定位问题。

最后,在可观测性方面,我们期待 Kitex 框架能够提供全面的日志、追踪和指标收集功能,以便对AI链路进行全方位的监控和分析。这将有助于我们及时发现潜在的性能瓶颈和优化点,从而提升AI应用的性能和稳定性。

综上所述,我们对 [Kitex][Kitex] 框架在AI场景下的未来期待主要集中在**开箱即用的AI组件编排能力****灵活的AI组件编排能力**以及**传统框架能力在LLM链路上的适配**等方面。我们相信随着技术的不断进步和团队的深入合作,这些期待将逐渐变为现实,为AI应用的开发带来更大的便利和效率。

实际上,我们团队已经与 Kitex 团队展开了深入的合作,共同探讨如何在微服务框架中更好地支持 AI 场景。我们相信,在不久的将来,我们将能够推出一个 MVP 版本的解决方案,为业务开发人员提供一个简单、无缝地与 AI 能力结合的框架。这将是一个激动人心的时刻,我们期待着这一天的到来。

[Kitex]: http://github.com/cloudwego/kitex
2 changes: 1 addition & 1 deletion content/zh/cooperation/interface_testing.md
@@ -1,7 +1,7 @@
---
type: docs
title: "字节跳动微服务体系下接口测试平台实践"
linkTitle: "接口测试平台"
linkTitle: "字节跳动-接口测试平台"
weight: 6
---

Expand Down
Binary file added static/img/users/flow/flow1.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/img/users/flow/flow2.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/img/users/flow/flow3.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/img/users/flow/flow4.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 8e384a0

Please sign in to comment.