)
今天是第二天以下是这两天的知识点与该方法的体验。文章目录一、虚拟环境为什么不能直接用系统 Python二、项目骨架先分清代码应该放在哪里三、.gitignore保护不该提交的文件四、Git 基础commit 和 push 的区别五、Python 类型注解六、Pydantic 入门七、Pydantic 的校验与报错八、第一次 LLM API 调用九、messages 结构system、user、assistant十、封装 call_llm 函数十一、temperature 参数十二、多轮对话 chat(messages)两天的学习感受附加核心技术栈后端开发AI / LLM 应用工程化与部署技术栈一览一、虚拟环境为什么不能直接用系统 Python项目一开始先创建了虚拟环境.venv。虚拟环境的作用是隔离项目依赖。每个项目可以有自己独立的 Python 包和版本避免不同项目之间互相影响。比如ai-intern-agent/ .venv/常用命令python-m venv.venv.\.venv\Scripts\activate pip list命令行前面出现(.venv)说明当前已经进入虚拟环境。.venv不应该提交到 GitHub原因是体积大和本机 Python 环境相关别人可以通过requirements.txt重新安装依赖二、项目骨架先分清代码应该放在哪里项目不是随便堆文件而是要提前规划目录职责。当前项目结构大致是ai-intern-agent/ app/ api/ routes/ core/ schemas/ services/ main.py scripts/ tests/ docs/ .gitignore README.md目录职责app/正式应用代码app/main.py项目入口app/schemas/Pydantic 数据模型scripts/练习脚本或临时验证脚本tests/后续测试代码docs/学习记录和项目文档这两天踩过一个坑终端当前路径不在项目根目录时运行脚本会找不到app模块。后来理解了运行脚本时要确认自己在项目根目录pwd三、.gitignore保护不该提交的文件.gitignore用来告诉 Git 哪些文件不要提交。目前至少需要包含.venv/ __pycache__/ .env其中.env很重要因为它通常会保存 API Key 等敏感信息绝对不能提交到 GitHub。四、Git 基础commit 和 push 的区别这两天也练习了 Git 的基本流程git status git add.git commit-m提交说明git push origin main我之前误以为 commit 后 GitHub 就能看到代码后来发现不是这样。区别是git commit提交到本地仓库 git push推送到 GitHub 远程仓库简单记忆git add 选文件 git commit 存到本地 git push 上传 GitHub五、Python 类型注解类型注解主要不是给 Python 运行时强制检查用的而是为了让代码更清晰也方便 IDE 提示。示例defget_app_name()-str:returnAI Intern Agent- str表示这个函数预期返回字符串。类型注解的好处提高代码可读性方便编辑器提示后续配合工具检查代码质量让函数输入输出更明确六、Pydantic 入门Pydantic 用来定义数据模型和校验数据结构。普通dict很灵活但也容易出错比如字段名写错、类型不对Python 不一定会提醒。Pydantic 可以把数据结构固定下来。示例frompydanticimportBaseModelclassHealthResponse(BaseModel):status:strservice:strversion:str0.1.0这里定义了一个HealthResponse模型包含三个字段statusserviceversion其中version有默认值。创建对象health_responseHealthResponse(statusok,serviceai-intern-agent,)print(health_response.model_dump())输出{status: ok, service: ai-intern-agent, version: 0.1.0}可以看到即使没有手动传入versionPydantic 也会自动补上默认值。七、Pydantic 的校验与报错我还测试了错误输入bad_responseHealthResponse(status[not,a,string],serviceai-intern-agent,)因为status定义的是str但实际传入的是list所以 Pydantic 会抛出ValidationError。为了让程序不直接崩掉可以用try/except捕获frompydanticimportValidationErrortry:bad_responseHealthResponse(status[not,a,string],serviceai-intern-agent,)print(bad_response.model_dump())exceptValidationErroraserror:print(有错误:)print(error)这让我理解了 Pydantic 的几个核心能力定义数据结构校验字段类型提供默认值用.model_dump()转成普通字典报错信息能指出哪个字段有问题八、第一次 LLM API 调用Day1 下午的内容是跑通第一次 LLM API 调用。大致流程是.env 里保存 API Key ↓ python-dotenv 读取环境变量 ↓ OpenAI SDK 创建 client ↓ client.chat.completions.create(...) ↓ 读取模型回复示例结构importosfromdotenvimportload_dotenvfromopenaiimportOpenAI load_dotenv()api_keyos.getenv(DEEPSEEK_API_KEY)base_urlos.getenv(DEEPSEEK_BASE_URL)modelos.getenv(LLM_MODEL)clientOpenAI(api_keyapi_key,base_urlbase_url,)responseclient.chat.completions.create(modelmodel,messages[{role:system,content:You are a helpful assistant.},{role:user,content:你好请用一句话介绍你自己},],)print(response.choices[0].message.content)这里没有把 API Key 写死在代码里而是从.env读取。九、messages 结构system、user、assistantLLM API 里的messages是一个列表每条消息都有role和content。常见角色system设定模型角色、规则、输出风格 user用户输入的问题或任务 assistant模型之前的回复示例messages[{role:system,content:You are a helpful assistant.},{role:user,content:什么是 RAG},]不能把所有内容都塞进user里因为工程上要职责分离system放稳定规则user放本次任务输入assistant放历史回复这样后面封装函数、多轮对话和 Agent 状态管理都会更清晰。十、封装 call_llm 函数原因是如果每次都复制一大段client.chat.completions.create(...)代码会重复而且不方便维护。封装后defcall_llm(prompt:str,system_prompt:str,temperature:float0.7,)-str:messages[]ifsystem_prompt:messages.append({role:system,content:system_prompt})messages.append({role:user,content:prompt})responseclient.chat.completions.create(modelmodel,messagesmessages,temperaturetemperature,)returnresponse.choices[0].message.content调用replycall_llm(prompt请用一句话描述什么是 AI Agent,system_promptYou are a helpful assistant.,temperature0.7,)print(reply)封装函数的好处减少重复代码后续更容易修改模型参数业务逻辑和 API 调用逻辑分开方便复用到 FastAPI 或 Agent 工作流里十一、temperature 参数temperature控制模型输出的随机性。实验结果temperature0三次输出几乎一样更稳定temperature1三次输出变化更明显更发散适用场景temperature0 适合分类、字段抽取、JSON 输出、JD 分析等稳定任务 temperature1 适合头脑风暴、文案生成、博客标题、创意表达等开放任务后面做 JD 分析和结构化输出时应该优先使用较低的 temperature。十二、多轮对话 chat(messages)最后实现了多轮对话函数defchat(messages:list[dict])-str:responseclient.chat.completions.create(modelmodel,messagesmessages,)returnresponse.choices[0].message.content测试流程messages[{role:system,content:You are a helpful assistant.},{role:user,content:什么是 RAG},]first_replychat(messages)print(first_reply)messages.append({role:assistant,content:first_reply})messages.append({role:user,content:它和微调有什么区别})second_replychat(messages)print(second_reply)这里最重要的理解是LLM 不会自动记住上一次脚本调用的内容。如果想让它理解第二轮问题里的“它”就必须把前面的历史 messages 一起传给模型。也就是说多轮对话的上下文是我们自己维护的。两天的学习感受跟着AI的节奏来会发现时间根本用不完我安排3小时的学习计划真实执行时一个小时即可完成所以我决定将时间驱动改为知识点驱动这样ai在引领学习时不会局限于当日任务状态好时进度也会更快。附加核心技术栈后端开发FastAPI— Web 框架路由设计、依赖注入、中间件、文件上传、流式响应、WebSocketPydantic v2— 数据校验与序列化嵌套模型、字段约束、自定义校验器SQLAlchemy 2.0 SQLite— ORM 数据持久化模型定义、会话管理、关系映射async/await httpx— 异步编程异步 HTTP 调用 LLM APIpytest— 测试体系fixture、TestClient、mock、覆盖率AI / LLM 应用OpenAI / DeepSeek API— LLM 调用、Prompt 工程、结构化输出RAG 全链路— Embedding 向量化、文本切分、Chroma 向量数据库、Top-K 检索Tool Calling— LLM 函数调用工具 schema 定义与执行LangGraph— Agent 工作流编排状态图、条件路由、多节点协作工程化与部署Docker docker-compose— 容器化部署多环境配置、健康检查GitHub Actions— CI/CD 自动化lint → test → build → deployRender / Railway— 云端部署上线structlog— 结构化日志request_id 链路追踪、错误码体系JWT API Key— 认证鉴权与接口安全技术栈一览语言 Python 3.12 ────────────────────────────────── 后端框架 FastAPI · Uvicorn · Pydantic v2 数据库 SQLAlchemy 2.0 · SQLite 异步 async/await · httpx 测试 pytest · pytest-cov AI/LLM OpenAI API · DeepSeek API · Prompt Engineering RAG Embedding · Chroma · 文本切分 · Top-K检索 Agent Tool Calling · LangGraph DevOps Docker · docker-compose · GitHub Actions 部署 Render · Railway 工程规范 ruff · pre-commit · structlog · JWT