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

输出 conda 23.x 及以上

安装 Miniconda

docker

输出 Docker version 2x.x

装 Docker Desktop for Windows,启用 WSL2 后端

git

输出 git version 2.x

装 Git for Windows

pwd

E:\HistoryAgent

cd E:\HistoryAgent

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)

新手必踩的坑

现象

原因

解决

conda activate 报 "Run 'conda init'"

shell 未初始化

执行 conda init powershell,重开终端

激活了但 python 还是系统版本

PATH 顺序问题 / 没重开终端

where.exe python 检查,重开终端再 conda activate histagent

PowerShell 禁止运行脚本

执行策略

Set-ExecutionPolicy -Scope CurrentUser RemoteSigned

conda create 卡住不动

镜像慢

配清华源(见下)

可选:换国内源(强烈建议,装包快很多)

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为什么要分层?

层

职责

不允许做什么

api

HTTP/SSE 协议、参数校验、错误码

不允许写业务逻辑、不允许直接调 LLM

agent

决策循环、提示词、状态管理

不允许直接连数据库

tools

单个能力的实现(检索/换算/查询)

不允许知道 HTTP 存在

memory

上下文窗口、摘要、缓存策略

不允许直接写 SQL

storage

仓储层,屏蔽 PG/Redis/Mongo 差异

不允许写业务判断

infra

日志、重试、异常、监控

不被业务层反向依赖

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

https://api.deepseek.com/v1

deepseek-chat

便宜、中文强、支持函数调用,首选

阿里通义

https://dashscope.aliyuncs.com/compatible-mode/v1

qwen-plus / qwen-turbo

有免费额度,兼容性好

智谱

https://open.bigmodel.cn/api/paas/v4

glm-4-flash

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 场景必须做。

Logo

更多推荐