跳到主要内容

第六练:基于 LLM 的"叙事经济学"量化分析系统

课程目标:从零构建一个能够读取金融新闻、量化市场叙事、并支持结构化数据输出的 AI 系统。 适用人群:金融科技开发者、量化研究员、数据分析师。 核心代码库sentiment.py(基于 LangChain)


1. 背景与痛点

1.1 什么是叙事经济学?

核心理论:引用诺奖得主 Robert Shiller 的《叙事经济学》。他认为市场波动不仅源于数据(如利率、财报),更源于**"故事(Narrative)"**在社会中的传播。

量化难题

  • K 线是"结果":价格波动是果,叙事是因。
  • 传统 NLP 的局限:基于词频统计(Bag of Words)的方法无法理解语境。例如,"利空出尽是利好"这句话,传统模型看到"利空"会判负面,而 LLM 能理解这是正面信号。

1.2 我们的解决方案

  • 输入:非结构化的每日财经新闻流。
  • 核心引擎:利用 LLM(Large Language Model)的语义理解能力 + 结构化输出技术
  • 输出结构化数据(JSON) —— 这是本练重点。只有将模糊的文字转化为结构化的表格数据,才能存入数据库,才能进行回测。

2. 数据契约与提示词工程

2.1 定义"模具":Pydantic Data Model

在让 AI 工作前,必须先定义"输出长什么样"。我们使用 Python 的 Pydantic 库充当数据契约。这不仅是定义数据,更是对 AI 的一种约束。

from pydantic import BaseModel, Field
from typing import List

class IndustrySignalSummary(BaseModel):
"""单个行业的每日信号摘要"""
industry_name: str = Field(description="行业名称")
# 强制要求列表格式,且必须提取实质性内容
positive_signals: List[str] = Field(description="实质性利好信号(如补贴、增长),忽略空话")
negative_signals: List[str] = Field(description="实质性利空信号(如处罚、下滑)")
daily_signal_bullet_points: List[str] = Field(description="3-5条核心要点摘要")

class PolicyAttribution(BaseModel):
"""政策归因:解决可解释性问题"""
key_event: str
quote_text: str = Field(description="必须引用原文,作为证据")

class ReportRiskAnalysis(BaseModel):
"""最终输出的完整报告结构"""
industry_signal_summaries: List[IndustrySignalSummary]
# 强制约束分数在 0-100 之间,防止 AI 产生幻觉数值
daily_macro_sentiment_score: int = Field(ge=0, le=100, description="0-100分,50为中性")
# 关键:要求 AI 提供原文证据
key_policy_attributions: List[PolicyAttribution]

2.2 提示词工程(Prompt Engineering)

  • Role(角色):Quantitative Financial Analyst(激活模型的金融领域权重,让它像分析师一样思考)。
  • Constraints(约束):明确要求 "Ignore generic slogans"(过滤噪音)。
  • Evidence(证据):要求 "Quote specific wording"(引用原文)。这是解决大模型幻觉的核心手段——没有证据,就不准打分。

3. 核心技术深度解析——三种输出策略

这是本系统的核心架构。我们在 sentiment.py 中实现了三种不同的 Agent,代表了 LLM 应用开发的三个阶段。我们将从 API 原理、稳定性和适用场景三个维度进行对比。

3.1 策略一:ProviderAgent(Native Structured Output)

【推荐方案】 利用模型厂商(OpenAI/Anthropic)底层的原生 JSON 模式。

# 直接将 Pydantic 类传给 response_format
self.agent = create_agent(
model=self.model,
response_format=ReportRiskAnalysis
)
  • 技术原理:LangChain 将 Pydantic 类转换为 JSON Schema,通过 API 的 response_format 参数传递给模型。
  • 底层约束:模型在推理层(Inference Layer)被强制约束。如果模型想生成一个不符合格式的字符(例如在 int 字段生成字母),会被底层引擎直接屏蔽。

3.2 策略二:ToolAgent(Tool/Function Calling)

【通用/兼容方案】 利用 LLM 的"工具调用"能力来"截获"结构化数据。

from langchain.agents.structured_output import ToolStrategy

# 将 Schema 包装为一个"工具策略"
self.agent = create_agent(
model=self.model,
response_format=ToolStrategy(ReportRiskAnalysis)
)
  • 技术原理(核心:参数截获 Intercept):我们告诉 LLM 有一个函数叫 submit_report(score, signals...),必须填对参数才能提交分析报告。LLM 分析完文本后,为了"调用"这个工具,它会生成一段标准的 JSON 参数(例如 {"score": 80, "signals": [...]})。

3.3 策略三:UnstructuredAgent(Freeform Text)

【对照组方案】 传统的聊天模式。

response_format=None  # 不限制格式

3.4 三种策略对比

维度ProviderAgentToolAgentUnstructuredAgent
格式控制response_format=Pydantic模型response_format=ToolStrategy(schema)response_format=None
格式准确率最高,输出与 Schema 严格一致较高,跨模型兼容性更好最低,输出格式完全自由
依赖依赖模型原生支持独立于特定 Provider无依赖
灵活性较低中等,需要更多提示工程最高
后处理无需少量需要后处理解析
结构化输出与模型能力的权衡
  • 约束导致能力下降:与自由文本生成相比,强制模型生成结构化输出(尤其是 JSON)会导致推理能力显著下降。
  • 约束越强,下降越多:格式限制越严格(如必须符合特定的 JSON Schema),模型的任务表现通常越差。
  • 原因:格式约束限制了模型的"生成空间",使得模型不得不分配注意力去满足格式要求,从而挤压了进行深度推理(Chain-of-Thought)的空间。

📎 参考文献Let Me Speak Freely? A Study on the Impact of Format Restrictions on Performance of Large Language Models


4. 应用场景与扩展方向

4.1 量化策略集成

  • 行业轮动(Industry Rotation):统计 JSON 中 positive_signals 频次。

    • 策略:做多"利好叙事"最强的行业,做空"利空叙事"最强的行业。
  • 风险预警(Risk Alert):当 sentiment_score < 40negative_signals 激增时。

    • 策略:触发风控系统的自动减仓逻辑,或发送邮件给交易员。

4.2 扩展方向

  • 多模态(Multimodal):不仅读文字,还要用 GPT-4o 读新闻配图(如会议现场图)、K 线图。
  • 实时流(Streaming):接入 Kafka/News API,将 batch_process 改为实时事件驱动。实现毫秒级信号推送:新闻发出 → LLM 分析 → 交易信号。
  • 知识图谱(Knowledge Graph):将提取的 Policy → Industry 关系存入图数据库。挖掘隐形的政策传导链(例如:A 行业的补贴如何传导至 B 行业)。

📋 小结

步骤内容关键技术
1叙事经济学背景LLM 语义理解 vs 传统 NLP
2数据契约定义Pydantic BaseModel + Field 约束
3三种输出策略Provider / Tool / Unstructured
4应用与扩展行业轮动、风险预警、多模态

掌握结构化输出技术后,你就能将 LLM 的分析能力转化为可量化、可回测的数据资产!🚀