Skip to content

Commit b1d115e

Browse files
fix: markdown lint error (missing blank line)
1 parent bc7ae04 commit b1d115e

File tree

21 files changed

+550
-70
lines changed

21 files changed

+550
-70
lines changed

01-tutorials/workshop/session1/.env.sample renamed to 01-tutorials/workshop/session1/langchain_agent_deploy_sample/.env.sample

File renamed without changes.

01-tutorials/workshop/session1/README.md renamed to 01-tutorials/workshop/session1/langchain_agent_deploy_sample/README.md

Lines changed: 48 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88

99
我们将对比 `langchain_agent.py` (原生实现) 和 `agent.py` (AgentKit 适配版),改造过程仅需以下 **3 点** 极小改动:
1010

11-
1. **引入 SDK 并初始化应用**
11+
1. **引入 SDK 并初始化应用**
12+
1213
```python
1314
# 引入 AgentKit SDK
1415
from agentkit.apps import AgentkitSimpleApp
@@ -17,38 +18,41 @@
1718
app = AgentkitSimpleApp()
1819
```
1920

20-
2. **标记入口函数**
21+
2. **标记入口函数**
2122
使用 `@app.entrypoint` 装饰器标记您的主逻辑函数。
23+
2224
```python
2325
@app.entrypoint
2426
async def run(payload: dict, headers: dict):
2527
# 您的业务逻辑...
2628
```
2729

28-
3. **按照标准协议返回**
30+
3. **按照标准协议返回**
2931
将原本直接打印到控制台的输出,改为 `yield` 返回标准 JSON 格式的 Event 数据。
32+
3033
```python
3134
# 原生 LangChain: print(chunk)
3235
# AgentKit 适配:
3336
yield json.dumps(event_data)
3437
```
38+
3539
这些改动是非侵入式的,您原有的 Chain 定义、Tool 定义和 Prompt 逻辑完全不需要修改。
3640

3741
## 核心功能
3842

39-
1. **构建 LangChain Agent**:使用 LangChain 1.0 标准范式构建具备工具调用能力的 ReAct Agent。
40-
2. **AgentKit 快速适配**:通过 SDK 将本地 Agent 转换为生产级微服务,无需修改核心 Chain 逻辑。
41-
3. **云端一键部署**:利用 AgentKit CLI 实现代码打包、镜像构建及环境变量的自动同步。
43+
1. **构建 LangChain Agent**:使用 LangChain 1.0 标准范式构建具备工具调用能力的 ReAct Agent。
44+
2. **AgentKit 快速适配**:通过 SDK 将本地 Agent 转换为生产级微服务,无需修改核心 Chain 逻辑。
45+
3. **云端一键部署**:利用 AgentKit CLI 实现代码打包、镜像构建及环境变量的自动同步。
4246

4347
## Agent 能力
4448

4549
本 Agent 具备以下基础能力:
4650

47-
- **自动化推理**:基于 ReAct 范式,自动分析用户问题并规划工具调用顺序。
48-
- **工具调用**
49-
- `get_word_length`: 计算单词长度。
50-
- `add_numbers`: 执行数值加法运算。
51-
- **流式响应**:支持 SSE 标准协议,实时输出思考过程和最终结果。
51+
- **自动化推理**:基于 ReAct 范式,自动分析用户问题并规划工具调用顺序。
52+
- **工具调用**
53+
- `get_word_length`: 计算单词长度。
54+
- `add_numbers`: 执行数值加法运算。
55+
- **流式响应**:支持 SSE 标准协议,实时输出思考过程和最终结果。
5256

5357
## 目录结构说明
5458

@@ -66,32 +70,40 @@ session1/
6670

6771
### 前置准备
6872

69-
1. **依赖安装**
70-
```bash
71-
uv sync
72-
source .venv/bin/activate
73-
```
73+
1. **依赖安装**
7474

75-
2. **配置环境变量**
76-
```bash
77-
cp .env.sample .env
78-
# 编辑 .env 文件,填入 OPENAI_API_KEY 等必填项
79-
```
75+
```bash
76+
uv sync
77+
source .venv/bin/activate
78+
```
79+
80+
2. **配置环境变量**
81+
82+
```bash
83+
cp .env.sample .env
84+
# 编辑 .env 文件,填入 OPENAI_API_KEY 等必填项
85+
86+
# 火山引擎访问凭证(必需)
87+
export VOLCENGINE_ACCESS_KEY=<Your Access Key>
88+
export VOLCENGINE_SECRET_KEY=<Your Secret Key>
89+
```
8090

8191
### 调试方法
8292

8393
**方式一:运行原生脚本** (验证 Agent 逻辑)
94+
8495
```bash
8596
uv run langchain_agent.py
8697
```
8798

8899
**方式二:运行 AgentKit 服务** (模拟生产环境)
100+
89101
```bash
90102
# 启动服务 (监听 8000 端口)
91103
uv run agent.py
92104

93105
# 在新终端运行客户端测试
94-
uv run local_client.py
106+
uv run client.py
95107
```
96108

97109
## AgentKit 部署
@@ -103,6 +115,7 @@ uv run local_client.py
103115
```bash
104116
agentkit config
105117
```
118+
106119
此命令会引导您选择项目空间和镜像仓库等信息,生成 `agentkit.yaml`
107120

108121
### 2. 部署上线
@@ -119,31 +132,31 @@ agentkit launch
119132

120133
```bash
121134
# <URL> 是 launch 命令输出的服务访问地址
122-
agentkit invoke --url <URL> 'Hello, can you calculate 10 + 20 and tell me the length of the word "AgentKit"?'
135+
agentkit invoke 'Hello, can you calculate 10 + 20 and tell me the length of the word "AgentKit"?'
123136
```
124137

125138
## 示例提示词
126139

127-
- "What is the length of the word 'Volcengine'?"
128-
- "Calculate 123 + 456."
129-
- "Hello, can you calculate 10 + 20 and tell me the length of the word 'AgentKit'?"
130-
- "Tell me a fun fact about Python." (此Agent不具备通用知识,会尝试使用工具或拒绝回答)
140+
- "What is the length of the word 'Volcengine'?"
141+
- "Calculate 123 + 456."
142+
- "Hello, can you calculate 10 + 20 and tell me the length of the word 'AgentKit'?"
143+
- "Tell me a fun fact about Python." (此Agent不具备通用知识,会尝试使用工具或拒绝回答)
131144

132145
## 效果展示
133146

134-
- **本地脚本**:终端直接输出 ReAct 思考链,展示 Agent 的推理过程和最终结果。
135-
- **HTTP 服务**:客户端接收 SSE 流式事件,包含详细的 `on_llm_chunk` (LLM思考过程)、`on_tool_start` (工具调用开始)、`on_tool_end` (工具调用结束) 等状态信息,提供丰富的交互体验。
147+
- **本地脚本**:终端直接输出 ReAct 思考链,展示 Agent 的推理过程和最终结果。
148+
- **HTTP 服务**:客户端接收 SSE 流式事件,包含详细的 `on_llm_chunk` (LLM思考过程)、`on_tool_start` (工具调用开始)、`on_tool_end` (工具调用结束) 等状态信息,提供丰富的交互体验。
136149

137150
## 常见问题
138151

139-
- **Q: 为什么提示 API Key 无效?**
140-
- A: 请确保 `.env` 文件中的 `OPENAI_API_KEY` 或其他模型服务商的 API Key 配置正确,且 `OPENAI_API_BASE` 与您使用的服务商(如火山方舟、OpenAI)匹配。
152+
- **Q: 为什么提示 API Key 无效?**
153+
- A: 请确保 `.env` 文件中的 `OPENAI_API_KEY` 或其他模型服务商的 API Key 配置正确,且 `OPENAI_API_BASE` 与您使用的服务商(如火山方舟、OpenAI)匹配。
141154

142-
- **Q: 部署时环境变量未生效?**
143-
- A: 请确认 `.env` 文件位于运行 `agentkit launch` 命令的当前项目根目录下。CLI 会自动查找并同步该文件。
155+
- **Q: 部署时环境变量未生效?**
156+
- A: 请确认 `.env` 文件位于运行 `agentkit launch` 命令的当前项目根目录下。CLI 会自动查找并同步该文件。
144157

145-
- **Q: Agent 无法回答通用知识问题?**
146-
- A: 本示例 Agent 主要演示工具调用能力,未集成通用知识库。如需回答通用知识,请扩展 Agent 的工具集或连接到知识库。
158+
- **Q: Agent 无法回答通用知识问题?**
159+
- A: 本示例 Agent 主要演示工具调用能力,未集成通用知识库。如需回答通用知识,请扩展 Agent 的工具集或连接到知识库。
147160

148161
## 代码许可
149162

01-tutorials/workshop/session1/agent.py renamed to 01-tutorials/workshop/session1/langchain_agent_deploy_sample/agent.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
from dotenv import load_dotenv
66
from agentkit.apps import AgentkitSimpleApp
77
import logging
8-
import asyncio
98
import json
109

1110

@@ -14,38 +13,43 @@
1413
logger = logging.getLogger(__name__)
1514
logger.setLevel(logging.INFO)
1615

16+
1717
# 1. Define tools
1818
@tool
1919
def get_word_length(word: str) -> int:
2020
"""Returns the length of a word."""
2121
return len(word)
2222

23+
2324
@tool
2425
def add_numbers(a: int, b: int) -> int:
2526
"""Adds two numbers together."""
2627
return a + b
2728

29+
2830
# Create the agent
2931
# Fix: Ensure environment variables are mapped to the correct arguments
3032
agent = create_agent(
3133
model=ChatOpenAI(
3234
model=os.getenv("MODEL_NAME", "gpt-4o-mini"),
3335
api_key=os.getenv("OPENAI_API_KEY"),
3436
base_url=os.getenv("OPENAI_API_BASE", "https://api.openai.com/v1"),
35-
temperature=0
37+
temperature=0,
3638
),
3739
tools=[get_word_length, add_numbers],
38-
system_prompt="You are a helpful assistant. You have access to tools to help answer questions."
40+
system_prompt="You are a helpful assistant. You have access to tools to help answer questions.",
3941
)
4042

4143

4244
app = AgentkitSimpleApp()
45+
46+
4347
@app.entrypoint
4448
async def run(payload: dict, headers: dict):
4549
prompt = payload.get("prompt")
4650
user_id = headers.get("user_id")
4751
session_id = headers.get("session_id")
48-
52+
4953
# Default values if still missing
5054
user_id = user_id or "default_user"
5155
session_id = session_id or "default_session"
@@ -55,17 +59,17 @@ async def run(payload: dict, headers: dict):
5559
)
5660

5761
inputs = {"messages": [{"role": "user", "content": prompt}]}
58-
62+
5963
# stream returns an iterator of updates
6064
# To get the final result, we can just iterate or use invoke
6165
async for chunk in agent.astream(inputs, stream_mode="updates"):
6266
# chunk is a dict with node names as keys and state updates as values
6367
for node, state in chunk.items():
6468
logger.debug(f"--- Node: {node} ---")
65-
69+
6670
if "messages" in state:
6771
last_msg = state["messages"][-1]
68-
72+
6973
for block in last_msg.content_blocks:
7074
# 返回的event_data数据结构要求符合 adk event规范: https://google.github.io/adk-docs/events/#identifying-event-origin-and-type
7175
event_data = {
@@ -76,11 +80,13 @@ async def run(payload: dict, headers: dict):
7680
}
7781
}
7882
yield json.dumps(event_data)
79-
83+
84+
8085
@app.ping
8186
def ping() -> str:
8287
return "pong!"
8388

89+
8490
async def local_test():
8591
"""Helper to run the agent locally without server"""
8692
print("Running local test...")
@@ -89,5 +95,6 @@ async def local_test():
8995
async for event in run({"prompt": query}, {"user_id": "1", "session_id": "1"}):
9096
print(f"Received event: {event}")
9197

98+
9299
if __name__ == "__main__":
93100
app.run(host="0.0.0.0", port=8000)

01-tutorials/workshop/session1/local_client.py renamed to 01-tutorials/workshop/session1/langchain_agent_deploy_sample/client.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,32 @@
11
import requests
22
import json
3-
import sys
3+
44

55
def main():
66
# Target URL
77
url = "http://localhost:8000/invoke"
8-
8+
99
# Payload parameters
1010
payload = {
1111
"prompt": "Hello, can you calculate 10 + 20 and tell me the length of the word 'AgentKit'?"
1212
}
13-
13+
1414
# Headers
15-
headers = {
16-
"user_id": "test_user_001",
17-
"session_id": "session_test_001"
18-
}
15+
headers = {"user_id": "test_user_001", "session_id": "session_test_001"}
1916

2017
print(f"Sending POST request to {url} with payload: {payload}")
2118

2219
try:
2320
response = requests.post(url, json=payload, headers=headers, stream=True)
24-
21+
2522
if response.status_code == 200:
2623
print("\n--- Streaming Response ---")
2724
for line in response.iter_lines():
2825
if line:
29-
decoded_line = line.decode('utf-8')
26+
decoded_line = line.decode("utf-8")
3027
if decoded_line.startswith("data: "):
3128
decoded_line = decoded_line[6:]
32-
29+
3330
if decoded_line.strip() == "[DONE]":
3431
continue
3532

@@ -44,11 +41,14 @@ def main():
4441
else:
4542
print(f"Request failed with status code: {response.status_code}")
4643
print(response.text)
47-
44+
4845
except requests.exceptions.ConnectionError:
49-
print("Error: Could not connect to the server. Is the agent running on port 8000?")
46+
print(
47+
"Error: Could not connect to the server. Is the agent running on port 8000?"
48+
)
5049
except Exception as e:
5150
print(f"An error occurred: {e}")
5251

52+
5353
if __name__ == "__main__":
5454
main()

0 commit comments

Comments
 (0)