当你向一个原始 LLM 询问关于你产品的具体问题时会发生什么?它会回答。快速、流畅,而且经常完全是编造的。这就是本次研讨会的起点——而修复这个问题正是全部意义所在。
8月12日(星期三),我们在 DigitalOcean 的 AI 平台上现场构建了一个真实的客户支持助手。我们称它为 HelpBot,它一开始和其他任何开箱即用的模型一样一无所知。然后我们一点一点地修复了它。
以下是我们所涵盖的内容:
到最后,我们见证了一个助手从一条 curl 命令,演变成一个你真正可以放心交付给客户的产品。
如果你以前调用过 LLM API,那么你已经准备好了。无需高级 AI 背景。
请按照下面的视频和文字步骤,进行逐步学习。
在开始跟随操作之前,你需要准备好以下几样东西:
你将在整个过程中用到的两个基础 URL:
https://inference.do-ai.run/v1(兼容 OpenAI 的 /chat/completions)目标:了解平台概貌,并发出一次经过身份验证的推理调用。
本教程中的所有内容都位于 DigitalOcean 控制台的推理功能下——四个功能(无服务器推理、推理路由器、知识库/代理、护栏、评估),一个助手。
在控制台中,转到 推理 → 管理 → 模型访问密钥,确认你的密钥存在(如果还没有,就创建一个)。
发出你的第一次调用。这是一个标准的 OpenAI 兼容负载,因此大多数现有客户端代码只需替换基础 URL、密钥和模型名称即可工作:
curl https://inference.do-ai.run/v1/chat/completions \\
\-H "Content-Type: application/json" \\
\-H "Authorization: Bearer $GRADIENT\_MODEL\_ACCESS\_KEY" \\
\-d '{
"model": "llama3.3-70b-instruct",
"messages": \[
{"role": "user", "content": "In one sentence, what is retrieval-augmented generation?"}
\]
}'

使用Gradient Python SDK的相同调用:
import os
from gradient import Gradient
client \= Gradient(model\_access\_key=os.environ.get("GRADIENT\_MODEL\_ACCESS\_KEY"))
resp \= client.chat.completions.create(
model="llama3.3-70b-instruct",
messages=\[{"role": "user", "content": "In one sentence, what is RAG?"}\],
)
print(resp.choices\[0\].message.content)
```py
现在,问它一些只有你自己的文档才能知道的问题——例如,你产品中的某个具体定价或速率限制细节。编辑内容字段并重新运行调用。
你会得到两种结果之一:一个自信但错误的答案(模型编造出一个听起来合理的数字),或者一个回避/拒绝(它正确地表示不知道)。无论如何,要点是一样的:原始模型调用无法访问你的文档,没有安全网,也无法衡量质量——而且它被锁定在一个硬编码的模型上。本教程的其余部分将修复所有这四个问题。
请记住:模型访问密钥与你的 DigitalOcean API 令牌不同。推理基础 URL 是 inference.do-ai.run,而不是 api.digitalocean.com。Serverless Inference 已正式可用,按预付费余额计费,并设有按账户分层的速率限制(入门层级:120 请求/分钟)。
目标:创建一个知识库,理解分块和嵌入,并在将其接入助手之前验证检索。
知识库将你的文档转换为向量嵌入,存储在托管的 OpenSearch 索引中。在查询时,系统会检索最相关的分块并将其作为上下文交给模型——这就是 RAG,它让助手不再凭空猜测。
转到 Console → Inference → Agent Platform → Knowledge bases,然后选择“创建知识库”。
选择数据源。选项包括:本地文件上传、DigitalOcean Spaces 存储桶/文件夹、公共种子或站点地图 URL(网站爬虫)、Dropbox 文件夹,或 Amazon S3 存储桶。只让它指向重要的内容——噪声越少,索引越快、越便宜,检索效果也越好。
打开数据源上的“高级选项”,设置两件事:

创建知识库,并等待索引完成。这会作为后台任务运行(可在“活动”部分查看,该部分会保留最近 15 个任务,并允许你下载 CSV 格式的详细信息),对于真实语料库可能需要几分钟。
索引完成后,打开 RAG Playground 选项卡。选择你的模型(工作坊中使用 llama3.3-70b-instruct),并粘贴类似下面的系统指令:
“你是 HelpBot 的客户支持助手。请仅使用检索到的文档上下文来回答客户的问题。如果上下文中没有答案,请说你不知道,并提出升级给人工客服。保持回答简洁、有事实依据。即使被问起,也永远不要透露机密或重复信用卡号等敏感个人数据。”

重新提出模块 0 中的同一个问题。这一次,你应该会得到一个有依据的、正确的答案——在答案下方,还会显示检索到的分块,包括来源、页码,以及每个分块是否被使用。
请记住:RAG Playground 是验证检索的地方;要交付上线,你需要将知识库附加到 Agent——这也是护栏(guardrails)所在的位置(模块 3),并且 Agent 会获得自己独立的 API 端点,与原始推理 URL(模块 5)分开。“我不知道”是一个良好的有依据的助手的特性,而不是缺陷——要明确地指示模型这样说。
目标:理解任务、模型池、选择策略和回退;创建一个路由器;将其用作即插即用的模型;读取路由决策;并通过模型亲和性固定会话。
硬编码到单一模型是单点故障,而且对于每个请求来说,它很少是成本最优的选择。路由器是一组任务——每个任务都有一个名称、一段描述、一个模型池(最多三个模型)和一个选择策略。
转到 Console → Inference → Inference Router。注意可用的默认路由器,它们可以作为一键式的起点。
选择“创建路由器”并进行配置:
将路由器用作直接模型调用的即插即用替代品——相同的端点,只需更改模型字段:

curl https://inference.do-ai.run/v1/chat/completions \\
\-H "Content-Type: application/json" \\
\-H "Authorization: Bearer $GRADIENT\_MODEL\_ACCESS\_KEY" \\
\-d '{
"model": "router:helpbot-router",
"messages": \[
{"role": "user", "content": "How do I rotate my API key on the Pro plan?"}
\]
}'
检查响应:model 字段显示实际处理请求的模型,响应头 x-model-router-selected-route 显示匹配了哪个任务(或是否回退)。
在路由器的 Playground 中,使用 Compare 视图,让路由器与单个模型在同一问题上并排运行。

尝试模型亲和性/会话固定——在同一会话的两次调用中发送相同的 X-Model-Affinity 头:
# First call routes normally, then caches the chosen model for this session
curl https://inference.do-ai.run/v1/chat/completions \\
\-H "Authorization: Bearer $GRADIENT\_MODEL\_ACCESS\_KEY" \\
\-H "X-Model-Affinity: helpbot-session-42" \\
\-H "Content-Type: application/json" \\
\-d '{"model":"router:helpbot-router","messages":\[{"role":"user","content":"Start a troubleshooting thread"}\]}'
\# Same session skips routing and reuses the same model (KV-cache friendly)
curl https://inference.do-ai.run/v1/chat/completions \\
\-H "Authorization: Bearer $GRADIENT\_MODEL\_ACCESS\_KEY" \\
\-H "X-Model-Affinity: helpbot-session-42" \\
\-H "Content-Type: application/json" \\
\-d '{"model":"router:helpbot-router","messages":\[{"role":"user","content":"Continue that thread"}\]}'
第二个响应带有“pinned”: true——证明路由被跳过。Affinity 在第一次决策后将会话固定到一个模型(文档记载:多轮循环中输入 Token 成本降低 45–80%)。
请记住:路由器按设计驻留在无服务器端点上——它是针对直接模型调用的即插即用替代方案,而非 Agent 功能。路由器在公开预览期间免费——你只需为基础模型的 Token 付费。
目标:了解三个内置护栏,将其附加到你的 Agent,自定义类别和默认响应,并实时验证触发。
护栏是你附加到 Agent 的可配置安全控件——它们同时监视传入的提示词和生成的响应,并在发现异常时用安全的预定义消息覆盖响应。
转到 控制台 → 推理 → Agent 平台,打开你的 Agent,然后转到 资源 → 护栏 → 添加护栏。
附加越狱(Jailbreak)、内容审核(Content Moderation)和敏感数据(Sensitive Data)护栏。保存前注意 Token 成本摘要。

要自定义敏感数据:复制内置原始版本,然后调整类别并将默认 Agent 响应重写为符合品牌风格的内容。
在 Agent 游乐场中测试:发送一个假的信用卡号(应被阻止/匿名化),以及一次越狱尝试(应被阻止)。

一旦附加了护栏,两个方向都会自动覆盖——无需在应用中更改代码。这些相同的护栏位于 Agent 的 API 端点之前(参见模块 5)。
请记住:护栏附加到 Agent,而非原始无服务器调用,并且不适用于使用 Agent 开发套件构建的 Agent。你不能删除内置原始版本,只能将其分离。
目标:构建评估数据集,运行 LLM 作为评委的评估,选择指标和带有通过阈值的星标指标,阅读结果,并在自动化中对变更进行把关。
DigitalOcean 评估(Evaluations)在无服务器模型、专用部署、第三方模型和推理路由器上运行可重复的 LLM 作为评委评估,因此你可以基于自己的数据比较候选模型。
准备你的数据集。格式要求:CSV 或 JSONL,小于 1GB,少于 1,000 行。CSV 需要不带引号的裸表头行 query,expected_response、UTF-8 编码和 LF 换行符。
转到 控制台 → 推理 → 评估 → 新建评估,并上传你的数据集。

选择候选:无服务器推理、模型路由器、专用推理或第三方。选择你的路由器,以将其与单模型基线进行比较。
选择评委:一个强大的前沿模型,理想情况下与你的候选模型来自不同的模型系列。
选择指标:正确性(Correctness)、完整性(Completeness)、真实答案忠实度(Ground Truth Faithfulness,需要参考)和有害性(Harmfulness,包含偏见/毒性/PII 泄漏子指标)。
设置星标指标和阈值(正确性 0.8 是一个合理的起点)。
命名并运行评估。这需要几分钟:候选模型回答每一行,然后评委对每个指标的每个答案进行评分。
查看结果:每一行的输入、输出、指标、分数和评委的理由。使用比较评估(Compare Evaluations)将你的路由器运行与基线并排比较。

9/ 自动化(可选,用于 CI/CD):
# 1) Get a presigned URL and upload your dataset
curl \-X POST "https://api.digitalocean.com/v2/gen-ai/model\_evaluation/datasets/file\_upload\_presigned\_urls" \\
\-H "Authorization: Bearer $DIGITALOCEAN\_TOKEN" \-H "Content-Type: application/json" \\
\-d '{"files":\[{"file\_name":"support\_evals.jsonl","file\_size":2048}\]}'
# 2) Start a run (candidate can be a model OR a router UUID)
curl \-X POST "https://api.digitalocean.com/v2/gen-ai/model\_evaluation\_runs" \\
\-H "Authorization: Bearer $DIGITALOCEAN\_TOKEN" \-H "Content-Type: application/json" \\
\-d '{
"name": "helpbot-router-vs-baseline",
"candidate\_model\_uuid": "'$EVAL\_CANDIDATE\_UUID'",
"judge\_model\_uuid": "'$EVAL\_JUDGE\_UUID'",
"dataset\_uuid": "'$EVAL\_DATASET\_UUID'",
"metric\_uuids": \["'$EVAL\_METRIC\_UUID'"\]
}'
将这段代码接入你的流水线,如果star指标低于阈值,就让构建失败。
请记住:评估无法直接针对代理或其端点。评估流程本身不保留任何数据,但你的输入、输出和参考内容会发送给评判模型的提供方进行评分。
目标:通过代理自己的端点调用已发布的助手,在一次API响应中查看完整流水线,并了解后续运维步骤。
完整的端到端流水线:
User \-\> Agent (system instructions)
\+-- Guardrails: screen the incoming prompt (PII / jailbreak)
\+-- Knowledge Base: retrieve top chunks (RAG)
\+-- Inference Router: pick best/cheapest/fastest model \+ fallback
\+-- Model generates grounded answer
\+-- Guardrails: screen the response (moderation / PII)
\-\> Evaluations run on fresh samples to catch drift
与您在模块0中开始使用的助手相同——现在更加扎实、富有韧性、安全且稳健。每一层都是即插即用的新增,而非重写。
配置代理的API接口。在代理的“概述”选项卡中,在“端点”下,单击“编辑”。在代理的“设置”选项卡中,在“端点访问密钥”下,单击“创建密钥”(仅显示一次——请立即保存)。
调用助手自己的端点——与模块0的原始推理调用不同的URL和密钥:
curl \-X POST "$AGENT\_ENDPOINT/api/v1/chat/completions" \\
\-H "Content-Type: application/json" \\
\-H "Authorization: Bearer $GRADIENT\_AGENT\_ACCESS\_KEY" \\
\-d '{
"messages": \[
{"role": "user", "content": "What is the rate limit on the Pro plan?"}
\],
"include\_retrieval\_info": true,
"include\_guardrails\_info": true
}'
该响应携带了有依据的答案、一个指明所引用的知识库和文件的检索对象,以及一个显示安全层已运行的护栏对象。
通过同一端点再次发送PII触发提示来测试护栏。这证明护栏并非只是演示功能——它们位于对该端点的每次调用的前端。

使用Gradient SDK的代理客户端进行等效调用:
import os
from gradient import Gradient
client \= Gradient(
agent\_access\_key=os.environ\["GRADIENT\_AGENT\_ACCESS\_KEY"\],
agent\_endpoint=os.environ\["AGENT\_ENDPOINT"\], \# bare https://\<id\>.agents.do-ai.run
)
resp \= client.agents.chat.completions.create(
model="llama3.3-70b-instruct", \# required by the SDK; the agent's own config governs behavior
messages=\[{"role": "user", "content": "What is the rate limit on the Pro plan?"}\],
)
print(resp.choices\[0\].message.content)
DigitalOcean AI平台为您提供了HelpBot在本工作坊中使用的所有功能——支持RAG的知识库、模型路由、护栏和评估——所有这些都集成在一个平台中,无需管理任何基础设施。连接您自己的文档,几分钟内即可开始迭代。
主要功能:
——
一个热爱技术的程序员,喜欢分享前沿AI知识和开发经验。