Day3——写config与重构main跟设计prompt
一、写 config让配置有个统一的家config 是什么、为什么要写之前项目里每个脚本都要重复写load_dotenv()再一个个os.getenv()去读 API Key、模型名。文件一多同样的代码抄好几遍换个配置要满项目搜而且os.getenv()拿到的东西没有类型约束、也没有默认值。所以我写了app/core/config.py用pydantic-settings的BaseSettings定义一个Settings类把所有配置集中在一处frompydantic_settingsimportBaseSettings,SettingsConfigDictclassSettings(BaseSettings):model_configSettingsConfigDict(env_file.env,extraignore)DEEPSEEK_API_KEY:strDEEPSEEK_BASE_URL:strLLM_MODEL:strdeepseek-chatAPP_NAME:strAI Intern AgentDEBUG:boolFalsesettingsSettings()config 的作用全项目只需from app.core.config import settings一处导入就能拿到所有配置每个字段有类型注解和默认值配置项一目了然以后改配置只改这一个文件。踩的坑没有显式声明 env_file第一次写完启动服务直接报错说DEEPSEEK_BASE_URL字段缺失。原因是BaseSettings默认不会自动读取.env文件必须显式声明它去哪读model_configSettingsConfigDict(env_file.env,extraignore)补上这一行后配置才真正从.env加载进来。以后写配置类第一件事就是加model_config。二、重构 main从函数堆变成真正的 Web 应用为什么要重构原来的main.py里只有一个普通函数根本不是一个能对外提供服务的 Web 应用——没有应用实例也没有任何接口。要让项目真正跑成一个后端服务必须重构。重构后的变化fromfastapiimportFastAPIfromapp.core.configimportsettingsfromapp.schemas.commonimportHealthResponse appFastAPI()app.get(/health,response_modelHealthResponse)defhealth():returnHealthResponse(statusok,servicesettings.APP_NAME,version0.1.0,app_namesettings.APP_NAME,debugsettings.DEBUG,)重构后创建了真正的 FastAPI 应用实例app项目可以用uvicorn启动成服务。有了第一个接口GET /health用来检查服务是否正常运行。用 Pydantic 模型HealthResponse约定返回数据的结构response_modelFastAPI 会自动校验响应并生成接口文档。启动后访问/health能返回 JSON访问/docs能看到自动生成的 Swagger 文档页。项目从一堆脚本正式变成了能启动、有接口、有文档的 Web 服务。三、Prompt 设计给 LLM 定好规矩为什么要设计 Prompt同样的问题问法不同LLM 给的答案质量天差地别。要让模型稳定输出我们想要的结果就得设计好 Prompt而不是随口一问。这里的关键是把 Prompt 分成两层System Prompt设定角色和规则整个任务里不变。User Prompt每次具体的任务输入会变化。我为 JD 分析写了一个 System Prompt设定资深招聘专家角色又写了一个模板函数把招聘文案拼成 User PromptSYSTEM_PROMPT_JD你是一位资深招聘专家熟悉当前就业市场以及各类岗位的职责与技能需求。defbuild_jd_user_prompt(jd_text:str)-str:returnf请分析下面这段文本提取出关键信息并且输出包含职位名称技能要求职责关键词四个部分{jd_text}跑通后输入一段 JD模型稳定返回了职位名称 / 技能要求 / 职责 / 关键词四个字段的结构化结果。对后续项目的作用这套 Prompt 结构是整个项目的核心地基。后面无论是把 JD 分析做成 POST 接口还是让模型输出规范的 JSON都建立在System 定角色、User 传输入、模板函数负责拼装这个模式之上。设计好 Prompt就是给后续所有 LLM 功能打好了统一的基础。