Skip to content

Commit 87ccba5

Browse files
committed
feat(docusaurus): add code block highlighting functionality with custom CSS styles
Add support for add/remove line highlighting in code blocks with corresponding CSS styling for visual indicators. Refactor existing CSS to use nested selectors and improve code organization. Update docusaurus configuration to include new highlight code block options for add-next-line, remove-next-line with corresponding start/end block markers. docs: add agent as model provider tutorial documentation Add new tutorial documentation covering how to use agents as model providers in the system, including configuration and usage examples. feat(docusaurus): 添加代码块高亮功能和自定义CSS样式 添加对代码块中添加/删除行高亮的支持,并为视觉指示器提供相应的CSS样式。 重构现有的CSS以使用嵌套选择器并改进代码组织。 更新docusaurus配置以包含新的高亮代码块选项,用于添加下一行、删除下一行 以及相应的开始/结束块标记。 docs: 添加代理作为模型提供者教程文档 添加新的教程文档,介绍如何在系统中使用代理作为模型提供者,包括配置和使用示例。 Change-Id: Ice22f64d4cdf5d30a5bc17e9f860a2bfa8832328 Signed-off-by: OhYee <[email protected]>
1 parent 59c1d8c commit 87ccba5

File tree

3 files changed

+241
-57
lines changed

3 files changed

+241
-57
lines changed
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
---
2+
sidebar_position: 20
3+
---
4+
5+
# 让 Agent 变成 “大模型供应商”
6+
7+
目前,AgentRun 快速创建的 Agent 以及 AgentRun SDK 的 AgentServer 已经支持了 OpenAI Chat Completions、AG-UI 协议。
8+
其中 OpenAI Chat Completions 是广泛使用的大模型调用协议,通过该协议,您可以像调用大模型一样使用您的 Agent。
9+
10+
:::info 将 Agent 变成 “大模型” 有什么优势
11+
12+
- **集成速度**: 将 Agent 封装为“模型”后可快速在 Open WebUI、Cherry Studio 等平台注册并使用,显著缩短集成时间。
13+
- **能力内置化**: 可把高级能力(访问内部 API、专用工具)作为模型能力内置,调用方无需重复实现。
14+
- **上层系统简化**: 外部系统只需调用统一模型接口,减少业务方的复杂度与维护成本。
15+
- **复用与共享**: 团队或生态内可共享同一“增强模型”,降低重复开发、促进能力沉淀。
16+
17+
:::
18+
19+
尽管 AgentRun 已经支持了通过 OpenAI Chat Completions 调用,但如果您进行详细的测试,会发现我们只处理了 `stream``messages` 字段。
20+
21+
这是因为 Agent 和大模型的使用场景不完全一致,Agent 交付的是一个经过详细调整,具备特定功能的整体。、
22+
以 AgentRun 探索页面的 “码呀码” 为例,这是一个可以帮助您撰写代码的模板,模板作者选择了 `qwen3-coder` 作为开发模型,并且通过大量测试找到了与系统提示词相匹配的模型参数。如果允许用户随意修改,则很可能会导致生成的代码完全无法使用。
23+
24+
对于大部分场景,我们并不建议您允许您的客户随意进行调整。但如果您的场景可以放开参数限制,那么只需要进行简单的调整即可将您的 Agent 变成真正的 “大模型供应商”
25+
26+
## 将快速创建 Agent 改造为 “大模型供应商”
27+
28+
以快速创建的 Agent 为例,首先在 AgentRun 控制台 - [Agent 运行时](https://functionai.console.aliyun.com/cn-hangzhou/agent/runtime/agent-list) 快速创建一个 Agent
29+
30+
![快速创建 Agent](https://img.alicdn.com/imgextra/i2/O1CN01oHHjTb1fuHWMrKuqr_!!6000000004066-2-tps-2342-2490.png)
31+
32+
Agent 配置可以根据您的实际需要进行调整。
33+
34+
创建完成后,将 Agent 转换为高代码的 Agent,此时您就可以根据实际需要随意调整 Agent 的实现了。
35+
36+
![将快速创建的 Agent 变为高代码的 Agent](https://img.alicdn.com/imgextra/i3/O1CN01HbWLCe1o2XabaHxlg_!!6000000005167-2-tps-2314-1006.png)
37+
38+
借助 WebIDE,您可以快速进行代码的修改。
39+
40+
![通过 WebIDE 修改代码](https://img.alicdn.com/imgextra/i1/O1CN01lO9y2P1PLRXdQVswP_!!6000000001824-2-tps-1256-374.png)
41+
42+
参考如下的方式,改造您的代码,即可通过 OpenAI Chat Completions 的 `model` 字段指定实际调用的模型。
43+
44+
```python title="main.py"
45+
# 如果 system_prompt_vars 非空,则展开 system_prompt
46+
if system_prompt_vars:
47+
system_prompt = expand_prompt_from_vars(system_prompt, system_prompt_vars)
48+
logger.info(f"Expanded system_prompt with variables: {system_prompt_vars}, system_prompt: {system_prompt}")
49+
50+
# add-start
51+
body = await request.raw_request.json()
52+
body_model = body.get("model", "")
53+
logger.info(f"model from body: {body_model}")
54+
# add-end
55+
56+
current_agent = create_agent(
57+
system_prompt=system_prompt, # 使用环境变量中的 PROMPT
58+
# remove-next-line
59+
model_name=model_name,
60+
# add-next-line
61+
model_name=body_model or model_name,
62+
api_key=api_key,
63+
base_url=base_url,
64+
model_parameter_rules=model_parameter_rules
65+
)
66+
67+
# 获取 thread_id(从 header 或生成一个)
68+
# 注意:HTTP header 名称在传递时可能会被转换为小写,所以同时检查大小写
69+
thread_id = (
70+
raw_headers.get('X-AgentRun-Session-ID') or
71+
raw_headers.get('x-agentrun-session-id') or
72+
raw_headers.get('X-Agentrun-Session-Id') or
73+
f"agentrun-{os.urandom(8).hex()}"
74+
)
75+
```
76+
77+
此时,您在调用时便可以随意调整模型的名称,可以参考的调用方式如下
78+
79+
```bash
80+
curl https://xxxxxx/Default/invocations/openai/v1/chat/completions -XPOST \
81+
-H "content-type: application/json" \
82+
-d '{
83+
"model": "deepseek-v3",
84+
"messages": [{"role": "user", "content": "你是什么模型?"}],
85+
"stream":true
86+
}'
87+
```
88+
89+
:::note 您还可以做什么
90+
91+
除去使用客户端传入的 `model` 外,您还可以
92+
93+
- 识别 `temperature` 等参数,控制传入模型的温度
94+
- 对模型进行映射,在您的客户传入 `my-model-lite` 调用 `qwen-flash`,在传入 `my-model-pro` 调用 `qwen3-max`
95+
- 改造传入框架的 model 字段,实现大模型的聚合能力。根据传入的模型名自动选择不同的模型平台
96+
- 识别客户端的工具,实现客户端工具调用
97+
98+
:::
99+
100+
## 让你的 Agent 也支持 API KEY 鉴权
101+
102+
大模型的鉴权通常使用 API KEY 进行鉴权,需要客户端在头部传入 `Authorization: Bearer sk-12345`
103+
104+
为了安全起见,我们也可以为我们的 Agent 配置 API KEY,在 Agent 编辑页面,配置 Agent 凭证
105+
106+
![配置 Agent 凭证](https://img.alicdn.com/imgextra/i2/O1CN01ioqKNi1EL1P6ESCno_!!6000000000334-2-tps-1696-1502.png)
107+
108+
在入站凭证选择 API KEY 模式,鉴权头部前缀选择 `Bearer`
109+
110+
![创建入站凭证](https://img.alicdn.com/imgextra/i1/O1CN017psVJV1asNnakxPfg_!!6000000003385-2-tps-1766-2392.png)
111+
112+
此时,客户端再次调用就必须携带 `Authorization` 头部了。通常,您只需要将不包含 `Bearer` 的部分传入客户端的 API KEY 的配置即可
113+
114+
115+
## 在 Cherry Studio 使用
116+
117+
以 Cherry Studio 为例,您可以在任意其他平台以类似的方式进行配置
118+
119+
通常需要的配置内容如下(如果可以选择的话,请选择 OpenAI Chat Completions 协议,而非 OpenAI Responses 协议)
120+
- **Base URL**: 在您的 Agent 访问地址(通常为 `xxxxx/invocations`)或您绑定的自定义域名后,增加 `/openai`
121+
- **API KEY**: 您的 Agent 凭证内容(不包含 `Bearer` 部分)
122+
- **模型**: 与您的 Agent 实际逻辑相关
123+
- 如果您按照上述的方式改造,则可以填入您选择的 AgentRun ModelService 配置的所有模型
124+
- 如果您增加了模型名称映射能力,则可以填入您的映射模型名称
125+
126+
![配置 Cherry Studio](https://img.alicdn.com/imgextra/i3/O1CN015qZODY1h1RKKjHfJa_!!6000000004217-2-tps-2214-1262.png)
127+
128+
下面是分别调用不同模型的结果
129+
130+
<div className="split2">
131+
132+
![qwen3-max](https://img.alicdn.com/imgextra/i1/O1CN01Yu9srC1WLd0nfB5nZ_!!6000000002772-2-tps-1700-530.png)
133+
134+
![deepseek-v3](https://img.alicdn.com/imgextra/i4/O1CN01xcKegf1fIGeDTMwqG_!!6000000003983-2-tps-1704-1028.png)
135+
136+
</div>

docusaurus.config.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,16 @@ const config: Config = {
201201
line: 'blur-next-line',
202202
block: { start: 'blur-start', end: 'blur-end' },
203203
},
204+
{
205+
className: 'highlight-code-block-add-line',
206+
line: 'add-next-line',
207+
block: { start: 'add-start', end: 'add-end' },
208+
},
209+
{
210+
className: 'highlight-code-block-remove-line',
211+
line: 'remove-next-line',
212+
block: { start: 'remove-start', end: 'remove-end' },
213+
},
204214
],
205215
},
206216
zoom: {

src/css/custom.css

Lines changed: 95 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -50,21 +50,21 @@
5050
gap: 4px;
5151
justify-content: center;
5252
align-items: center;
53-
}
5453

55-
.header-github-link::before {
56-
content: '';
57-
width: 24px;
58-
height: 24px;
59-
display: flex;
60-
background-color: var(--ifm-navbar-link-color);
61-
mask-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E");
62-
transition: background-color var(--ifm-transition-fast)
63-
var(--ifm-transition-timing-default);
64-
}
54+
&::before {
55+
content: '';
56+
width: 24px;
57+
height: 24px;
58+
display: flex;
59+
background-color: var(--ifm-navbar-link-color);
60+
mask-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E");
61+
transition: background-color var(--ifm-transition-fast)
62+
var(--ifm-transition-timing-default);
63+
}
6564

66-
.header-github-link:hover::before {
67-
background-color: var(--ifm-navbar-link-hover-color);
65+
&:hover::before {
66+
background-color: var(--ifm-navbar-link-hover-color);
67+
}
6868
}
6969

7070
.nodejs-icon::before {
@@ -86,23 +86,22 @@
8686
.img-with-caption {
8787
display: block;
8888
text-align: center;
89-
}
9089

91-
.img-with-caption > img {
92-
display: block;
93-
margin-left: auto;
94-
margin-right: auto;
95-
max-width: 100%;
96-
max-height: 30vh;
97-
}
90+
& > img {
91+
display: block;
92+
margin-left: auto;
93+
margin-right: auto;
94+
max-width: 100%;
95+
max-height: 30vh;
96+
}
9897

99-
.img-with-caption > figcaption.img-alt-text {
100-
display: block;
101-
font-size: 0.9em;
102-
color: #666;
103-
text-align: center;
104-
opacity: 0.95;
105-
font-size: 0.75em;
98+
& > figcaption.img-alt-text {
99+
display: block;
100+
font-size: 0.8em;
101+
color: #666;
102+
text-align: center;
103+
opacity: 0.95;
104+
}
106105
}
107106

108107
[data-theme='dark'] .img-with-caption > figcaption.img-alt-text {
@@ -125,52 +124,91 @@
125124
--highlight-color: #52b5d6;
126125
}
127126

127+
.highlight-code-block-add-line,
128+
.highlight-code-block-remove-line {
129+
/* --highlight-color: #069205; */
130+
border-left: 0 !important;
131+
padding-left: 0.25em !important;
132+
133+
&::before {
134+
margin-right: 0.25em;
135+
}
136+
}
137+
138+
.highlight-code-block-add-line {
139+
background-color: #dafae0 !important;
140+
141+
&::before {
142+
content: '+';
143+
}
144+
}
145+
146+
.highlight-code-block-remove-line {
147+
background-color: #ffeae8 !important;
148+
149+
&::before {
150+
content: '-';
151+
}
152+
}
153+
128154
.highlight-code-block-blur-line {
129155
--highlight-color: #d4d5d8;
130156
background: none !important;
131157
}
132158

133-
.highlight-code-block-blur-line .token,
159+
.highlight-code-block-blur-line,
134160
.highlight-code-block-blur-line:hover
135161
~ :not(.highlight-code-block-blur-line)
136-
~ .highlight-code-block-blur-line
137-
.token,
162+
~ .highlight-code-block-blur-line,
138163
.highlight-code-block-blur-line:has(
139164
~ :not(.highlight-code-block-blur-line)
140165
~ .highlight-code-block-blur-line:hover
141-
)
166+
) {
142167
.token {
143-
opacity: 0.5;
144-
filter: blur(2px);
145-
transition: all 0.2s ease-in-out;
168+
opacity: 0.5;
169+
filter: blur(2px);
170+
transition: all 0.2s ease-in-out;
171+
}
146172
}
147173

148-
/* div[class*='codeBlockContent']:hover .highlight-code-block-blur-line .token {
149-
opacity: 1;
150-
filter: blur(0);
151-
} */
152-
153-
.highlight-code-block-blur-line:hover .token,
154-
.highlight-code-block-blur-line:hover ~ .highlight-code-block-blur-line .token,
155-
.highlight-code-block-blur-line:has(~ .highlight-code-block-blur-line:hover)
174+
.highlight-code-block-blur-line:hover,
175+
.highlight-code-block-blur-line:hover ~ .highlight-code-block-blur-line,
176+
.highlight-code-block-blur-line:has(~ .highlight-code-block-blur-line:hover) {
156177
.token {
157-
opacity: 1;
158-
filter: blur(0);
159-
cursor: pointer;
160-
}
161-
162-
div[class*='codeBlockContent'] [class*='highlight-code-block'] {
163-
display: block;
164-
margin: 0 calc(-1 * var(--ifm-pre-padding));
165-
padding: 0 var(--ifm-pre-padding);
166-
padding-left: calc(1em - 3px);
167-
border-left-width: 3px;
168-
border-left-style: solid;
169-
background-color: rgb(from var(--highlight-color) r g b / 0.125);
170-
border-left-color: var(--highlight-color);
178+
opacity: 1;
179+
filter: blur(0);
180+
cursor: pointer;
181+
}
171182
}
172183

173184
div[class*='codeBlockContent'] {
174185
max-height: 30vh;
175186
overflow: auto;
187+
188+
[class*='highlight-code-block'] {
189+
display: block;
190+
margin: 0 calc(-1 * var(--ifm-pre-padding));
191+
padding: 0 var(--ifm-pre-padding);
192+
padding-left: calc(1em - 3px);
193+
border-left-width: 3px;
194+
border-left-style: solid;
195+
background-color: rgb(from var(--highlight-color) r g b / 0.125);
196+
border-left-color: var(--highlight-color);
197+
}
198+
}
199+
200+
.split2,
201+
.split3,
202+
.split4 {
203+
display: flex;
204+
}
205+
206+
.split2 > * {
207+
flex: 1 1 50%;
208+
}
209+
.split3 > * {
210+
flex: 1 1 33%;
211+
}
212+
.split4 > * {
213+
flex: 1 1 25%;
176214
}

0 commit comments

Comments
 (0)