从零开始制作一个中国历史agent1——环境搭建与项目骨架
0.开工前自检
0.1打开 PowerShell,逐条执行,把结果记下来。
# 1. conda 是否存在
conda --version
# 2. 有没有 Docker Desktop(Day7 才用,先确认装没装)
docker --version
# 3. git 是否存在
git --version
# 4. 当前目录
pwd
# 5. 系统架构(确认 64 位)
[System.Environment]::Is64BitOperatingSystem
|
检查项 |
期望 |
不满足怎么办 |
|---|---|---|
|
conda |
输出 |
安装 Miniconda |
|
docker |
输出 |
装 Docker Desktop for Windows,启用 WSL2 后端 |
|
git |
输出 |
装 Git for Windows |
|
pwd |
|
|
1.创建隔离环境(本项目的核心要求)
# 1. 创建环境:名字 histagent,Python 3.11
conda create -n histagent python=3.11 -y
# 2. 激活(每次开新终端都要执行这一步)
conda activate histagent
# 3. 验证:必须都指向 histagent 环境
python --version # 期望 Python 3.11.x
where.exe python # 期望路径里出现 envs\histagent
python -c "import sys; print(sys.executable)"
结果如下:

验收标准
-
python --version输出Python 3.11.x -
sys.executable路径包含envs\histagent -
提示符前面出现
(histagent)
新手必踩的坑
|
现象 |
原因 |
解决 |
|---|---|---|
|
|
shell 未初始化 |
执行 |
|
激活了但 |
PATH 顺序问题 / 没重开终端 |
|
|
PowerShell 禁止运行脚本 |
执行策略 |
|
|
|
镜像慢 |
配清华源(见下) |
可选:换国内源(强烈建议,装包快很多)
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --set show_channel_urls yes
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
2.创建目录骨架
2.1在 E:\HistoryAgent 下建立这个结构。先用 mkdir 建目录,再自己新建文件
E:\HistoryAgent
├── .env # 本地密钥,绝不提交
├── .env.example # 提交,写清有哪些变量、不给值
├── .gitignore
├── README.md
├── requirements.txt
├── docker-compose.yml
├── docs/
├── data/
│ ├── raw/ # 史料原始文本
│ └── processed/ # 切分/清洗后的数据
├── scripts/ # 一次性脚本:导入数据、跑评测
├── src/
│ └── histagent/
│ ├── __init__.py
│ ├── main.py # FastAPI 入口
│ ├── config.py # 配置加载
│ ├── api/ # 路由层
│ ├── agent/ # 编排层(ReAct / LangGraph)
│ ├── tools/ # 工具层
│ ├── memory/ # 记忆与上下文
│ ├── storage/ # PG / Redis / Mongo 访问
│ └── infra/ # 日志、异常、重试
└── tests/
2.2PowerShell 建目录
cd E:\HistoryAgent
mkdir data\raw, data\processed, scripts, tests, src\histagent\api, src\histagent\agent, src\histagent\tools, src\histagent\memory, src\histagent\storage, src\histagent\infra
2.3为什么要分层?
|
层 |
职责 |
不允许做什么 |
|---|---|---|
|
|
HTTP/SSE 协议、参数校验、错误码 |
不允许写业务逻辑、不允许直接调 LLM |
|
|
决策循环、提示词、状态管理 |
不允许直接连数据库 |
|
|
单个能力的实现(检索/换算/查询) |
不允许知道 HTTP 存在 |
|
|
上下文窗口、摘要、缓存策略 |
不允许直接写 SQL |
|
|
仓储层,屏蔽 PG/Redis/Mongo 差异 |
不允许写业务判断 |
|
|
日志、重试、异常、监控 |
不被业务层反向依赖 |
3.依赖清单 (先安装部分)
# ---- 基础 ----
fastapi==0.115.*
uvicorn[standard]==0.32.*
pydantic==2.*
pydantic-settings==2.*
python-dotenv==1.*
# ---- LLM ----
openai==1.* # 用 OpenAI 兼容协议调国内模型
httpx==0.27.*
# ---- 工程 ----
tenacity==9.* # 重试退避
loguru==0.* # 结构化日志
orjson==3.*
# ---- 开发 ----
pytest==8.*
pytest-asyncio==0.*
ruff==0.*
安装:
conda activate histagent
cd E:\HistoryAgent
pip install -r requirements.txt
pip list | Select-String "fastapi|openai|pydantic"
验收:`pip list` 能看到 fastapi / openai / pydantic 且版本符合。
(histagent) PS E:\HistoryAgent> pip list | Select-String "fastapi|openai|pydantic"
fastapi 0.115.14
openai 1.109.1
pydantic 2.14.3
pydantic_core 2.50.4
pydantic-settings 2.16.2
4.申请模型密钥(OpenAI 兼容协议
任选一家,优先选有免费额度且支持 tool_calls(函数调用)的。
|
平台 |
base_url |
常用模型 |
备注 |
|---|---|---|---|
|
DeepSeek |
|
|
便宜、中文强、支持函数调用,首选 |
|
阿里通义 |
|
|
有免费额度,兼容性好 |
|
智谱 |
|
|
flash 系列免费额度大 |
操作:注册 → 控制台 → API Keys → 新建 → 复制出来立刻存好(只显示一次)。
为什么要"OpenAI 兼容"? 因为它是一套事实标准:只要代码按 openai SDK 写,改 base_url + model 就能换厂商,不锁死供应商。
5..env 与配置加载
.env(自己创建,加进 .gitignore,记住,这个千万不能上传到github,除非你是土豪,共享apikey,有这好事记得私聊下我):
LLM_PROVIDER=deepseek
LLM_BASE_URL=https://api.deepseek.com/v1
LLM_API_KEY=sk-你的key
LLM_MODEL=deepseek-chat
LLM_TEMPERATURE=0.3
LLM_MAX_TOKENS=1024
APP_ENV=dev
LOG_LEVEL=INFO
.env.example(提交到仓库,只有键没有值):
LLM_PROVIDER=
LLM_BASE_URL=
LLM_API_KEY=
LLM_MODEL=
LLM_TEMPERATURE=0.3
LLM_MAX_TOKENS=1024
APP_ENV=dev
LOG_LEVEL=INFO
.gitignore
.env
__pycache__/
*.pyc
.venv/
.conda/
.pytest_cache/
.ruff_cache/
data/raw/*
data/processed/*
!data/raw/.gitkeep
logs/
*.log
.idea/
.vscode/
配置加载要点(在 src/histagent/config.py 里自己实现):
-
用
pydantic-settings的BaseSettings,model_config = SettingsConfigDict(env_file=".env") -
字段与
.env键名小写对应(llm_api_key↔LLM_API_KEY) -
全局单例:
settings = Settings(),其他模块from histagent.config import settings -
启动时校验:
llm_api_key为空就直接抛错退出,不要等调用时才 401 -
日志里永远不打印完整 key,打
sk-****1234形式
验收:python -c "from histagent.config import settings; print(settings.llm_model)" 能打印出模型名(需先把 src 加到路径或 pip install -e .)。
6.第一次大模型调用
新建 scripts/smoke_llm.py,写入:
# 参考思路:脚本要做三件事
# 1) 从 config 读配置
# 2) 用 openai SDK 调 chat.completions(普通 + 流式各一次)
# 3) 打印回复全文、耗时、token 用量
from histagent.config import settings
from openai import OpenAI
import time
client = OpenAI(api_key=settings.llm_api_key, base_url=settings.llm_base_url)
t0 = time.perf_counter()
resp = client.chat.completions.create(
model=settings.llm_model,
messages=[
{"role": "system", "content": "你是一位严谨的中国历史研究助手。"},
{"role": "user", "content": "用三句话说明安史之乱对唐朝财政的影响。"},
],
temperature=settings.llm_temperature,
max_tokens=settings.llm_max_tokens,
)
print("耗时:", round((time.perf_counter() - t0) * 1000), "ms")
print("回复:", resp.choices[0].message.content)
print("用量:", resp.usage)
运行:
conda activate histagent
cd E:\HistoryAgent
python -m scripts.smoke_llm # 或 python scripts/smoke_llm.py
验收清单
-
拿到中文回复,内容通顺
-
打印出了耗时、
prompt_tokens / completion_tokens / total_tokens -
再改成
stream=True,用for chunk in resp:逐块打印,能明显看到逐字输出 -
故意把 key 改错一位,看报什么错
这一步要理解的事
-
messages是有序列表,system定角色,user/assistant交替,模型没有记忆,历史全靠你每次传回去。 -
temperature:0-0.3 适合史料问答(稳定、少胡说),0.7+ 适合头脑风暴。 -
max_tokens限制的是输出长度,不是输入;超了会被截断(finish_reason=length)。 -
流式(stream)只降低首字延迟,不降低总耗时,但体验提升巨大——Agent 场景必须做。
更多推荐


所有评论(0)