顺着 main.py 读模型部分
第 2 节:Prompt 与结构化解析
Agent 不先写一段自由回答,而是先把问题变成程序能判断的字段。
1. 先看配置
MOCK_MODE 默认开启,保证没密钥也能启动。切到真实模型时填写代码顶部的 API Key。API Key 只保存在你本机代码里,不要上传;若误提交,应到服务商后台撤销并重新生成。
MOCK_MODE = True
OPENAI_API_KEY = ""
OPENAI_MODEL = "gpt-4o-mini"
OPENAI_BASE_URL = ""2. Schema 是模型与程序之间的约定
ResearchQuery 规定模型返回公司、市场、代码以及是否查询行情/资料。证券代码可以是 null;模型不确定时应该留空,而不是编一个代码。
class ResearchQuery(BaseModel):
company: str | None = Field(default=None, description="公司或证券名称")
market: Literal["CN", "HK", "US", "unknown"] = "unknown"
symbol: str | None = Field(default=None, description="无法确认时为 null")
needs_quote: bool = False
needs_search: bool = False3. Prompt 要把规则写清楚
系统消息负责稳定约束,用户消息只放本次问题。with_structured_output 让 LangChain 把模型响应解析并校验为 Pydantic 对象。
QUERY_PROMPT = ChatPromptTemplate.from_messages([
("system", "只提取用户明确提到的公司信息,不猜证券代码。判断是否需要行情或最新资料。"),
("human", "{question}"),
])
parsed = (QUERY_PROMPT | model.with_structured_output(ResearchQuery)).invoke(
{"question": question}
)Mock 模式用本地确定性规则代替模型解析,所以输出不会假装是模型生成。需要支持结构化输出的聊天模型才能使用真实模式。
4. 回到完整项目
上述代码已在第 1 节完整源码中,文件下载仍从实战首页获取。试着比较“最近有什么新闻”和“股价怎么样”这两类问题,观察 needs_search 与 needs_quote 的区别。