# 进入项目目录
cd ~/Documents/practice/agents
# 创建 day1 目录
mkdir -p day1
cd day1
# 创建虚拟环境
python3 -m venv venv
source venv/bin/activate
# 你会看到终端前面多了 (venv) 前缀,表示激活成功
# 安装依赖
pip install openai python-dotenv
venv ≈ Go 的 go.mod 项目隔离 / Java 的 Maven 项目pip install ≈ go get / Maven 加依赖source venv/bin/activate 才能进入这个"项目环境"pip freeze > requirements.txt
ep-2024xxxx-xxxxx.env 文件里,永远不要提交到 Git、不要发给任何人(包括 AI 助手)。我们的 .gitignore 已经屏蔽了 .env。
在 day1/ 目录下创建 .env 文件:
ARK_API_KEY=你的APIKey
ARK_ENDPOINT_ID=你的接入点ID
ARK_BASE_URL=https://ark.cn-beijing.volces.com/api/v3
再创建一个 .env.example(这个会提交到 Git,让别人知道格式):
ARK_API_KEY=your_api_key_here
ARK_ENDPOINT_ID=your_endpoint_id_here
ARK_BASE_URL=https://ark.cn-beijing.volces.com/api/v3
创建 demo1_single_chat.py:
"""
Demo 1: 单轮对话
最小可运行的 LLM 调用
"""
import os
from openai import OpenAI
from dotenv import load_dotenv
# 加载 .env 里的环境变量
load_dotenv()
# 初始化客户端(火山方舟兼容 OpenAI SDK)
client = OpenAI(
api_key=os.getenv("ARK_API_KEY"),
base_url=os.getenv("ARK_BASE_URL"),
)
# 发起对话
response = client.chat.completions.create(
model=os.getenv("ARK_ENDPOINT_ID"), # 火山用 endpoint_id 作为 model 参数
messages=[
{"role": "system", "content": "你是一个简洁友好的编程助手,回答不超过 100 字。"},
{"role": "user", "content": "请用一句话解释什么是 Agent。"},
],
)
# 打印结果
print("🤖 回答:", response.choices[0].message.content)
print("\n📊 Token 消耗:", response.usage)
python demo1_single_chat.py
🤖 回答: Agent 是能自主感知环境、决策并调用工具完成任务的智能程序。
📊 Token 消耗: CompletionUsage(completion_tokens=20, prompt_tokens=35, total_tokens=55)
这是 Agent 的雏形——能记住上下文 + 实时输出(体验更好)。
创建 demo2_chat_loop.py:
"""
Demo 2: 多轮对话 + Streaming
理解 messages 数组是如何"累积"上下文的
"""
import os
from openai import OpenAI
from dotenv import load_dotenv
load_dotenv()
client = OpenAI(
api_key=os.getenv("ARK_API_KEY"),
base_url=os.getenv("ARK_BASE_URL"),
)
# 对话历史 —— Agent 的"短期记忆"
messages = [
{"role": "system", "content": "你是一个耐心的编程导师,擅长 Python 和 Go。"},
]
print("💬 开始对话(输入 'exit' 退出,'clear' 清空历史)\n")
while True:
# 1. 拿用户输入
user_input = input("你: ").strip()
if user_input.lower() == "exit":
print("👋 再见!")
break
if user_input.lower() == "clear":
messages = messages[:1] # 保留 system prompt
print("🧹 历史已清空\n")
continue
if not user_input:
continue
# 2. 加进历史
messages.append({"role": "user", "content": user_input})
# 3. 调用 LLM(stream=True 让它一个字一个字吐出来)
stream = client.chat.completions.create(
model=os.getenv("ARK_ENDPOINT_ID"),
messages=messages,
stream=True,
)
# 4. 边收边打印,同时拼接完整回复
print("🤖 助手: ", end="", flush=True)
full_reply = ""
for chunk in stream:
delta = chunk.choices[0].delta.content
if delta:
print(delta, end="", flush=True)
full_reply += delta
print("\n")
# 5. 把 LLM 的回复也加进历史 —— 这样下一轮它才"记得"
messages.append({"role": "assistant", "content": full_reply})
python demo2_chat_loop.py
你: 我叫小明,在学 Go。
🤖 助手: 你好小明!...
你: 我叫什么名字?在学什么?
🤖 助手: 你叫小明,在学 Go 语言。 ← 记忆生效 ✅
你: clear
🧹 历史已清空
你: 我叫什么?
🤖 助手: 抱歉,我不知道... ← 清空后"失忆"
改造 demo2,加一个功能:
每轮对话结束后,打印本轮消耗的 token 数和累计 token 数
usage 一般在最后一个 chunk 里create() 里加 stream_options={"include_usage": True}chunk.usage 只在最后一个 chunk 有值,其他 chunk 是 None| 概念 | 一句话解释 |
|---|---|
messages 数组 | Agent 的记忆载体,[{role, content}, ...],role 有 system/user/assistant/tool 四种 |
| system prompt | 给 LLM 的"身份设定",通常放在第一条 |
stream=True | 流式返回,改善体验,不影响功能 |
| temperature | 0-2,越高越"有创意",Agent 场景一般 0.3-0.7 |
| endpoint_id | 火山方舟特色:不是模型名,而是你创建的"接入点 ID" |
收工前,你应该能:
system / user / assistant 三个 role 各是干嘛的| 报错 | 原因 & 解决 |
|---|---|
AuthenticationError | API Key 不对,检查 .env 是否有多余空格、引号 |
model not found | 填了模型名(如 doubao-pro-32k),应该填 endpoint_id(ep-xxx) |
Connection error | 网络问题,或 base_url 拼错了 |
ModuleNotFoundError: openai | 忘了 source venv/bin/activate |
| 命令行输不了中文 | Mac 一般没问题,如果是 Windows 参考 chcp 65001 |
Day 1 完成后,把代码提交到 Git:
cd ~/Documents/practice/agents
# 检查有哪些新文件(.env 应该被 .gitignore 屏蔽)
git status
# 添加 & 提交
git add day1/
git commit -m "Day 1: 环境搭建 + LLM 首次调用(单轮 + 多轮 Streaming)"
# 推送
git push
git status 里不应该出现 .env。如果出现了,说明 .gitignore 有问题,先解决再提交。
让 LLM 学会 调用工具——这是 Agent 从"聊天机器人"升级为"能做事的助手"的关键一步。你会写一个能:
tool_calls → tool_result 循环