An early financial-document RAG prototype exploring metadata-first retrieval and table-aware chunking.
FinAgent 来自 2024 年的一次早期金融 Agent / RAG 探索,面向基金年度报告、季度报告等包含 大量表格和强文档元数据的金融材料。项目最初尝试组合文档问答、数值计算、结构化信息抽取和 图表生成;归档版本保留并明确展示其中两个最重要的判断:
- **先使用 metadata 缩小文档范围,再进行内容检索。**基金名称、年份、季度和报告类型通常 已经能够排除大量无关报告。
- **表格需要独立于普通文本的结构化检索路径。**基金公告中的核心数字经常位于表格中;除了 保留完整表格,还应识别表头和指标行、检索相关行、解析比例/金额等类型化值,并返回能够 定位到具体表格行的证据。
FinAgent originated from an early financial Agent/RAG experiment in 2024. It focuses on fund annual and quarterly reports, where document metadata is highly informative and many important facts live in tables. The archived prototype demonstrates two ideas:
- Filter by metadata before content retrieval. Fund name, year, reporting period, and report type can sharply reduce the candidate document set.
- Give tables a dedicated structured retrieval path. Financial tables should preserve schemas and rows, retrieve metric-level evidence, normalize values such as ratios or amounts, and return row-level citations instead of being treated as ordinary prose.
user query
-> extract fund name, year and reporting period
-> filter candidate reports by metadata
-> route text and table blocks through different retrieval logic
-> select a relevant table and metric row
-> normalize typed values such as ratios and CNY amounts
-> return source + table-row citation + structured evidence
当前默认入口是一个不依赖 API key、向量数据库或外部模型的确定性演示:
- 从规范化文件名提取
fund_name、year、period和report_type; - 从用户问题中提取同类 metadata filter;
- 在语义/关键词排序之前执行文档级过滤;
- 将 Markdown 表格完整保留为单一
tableblock; - 显式保存表头、二维行结构以及表格所属报告的 metadata;
- 先选表格,再根据 query 与表头/指标行的匹配选择相关 row;
- 将
24.80%解析为value=0.248, unit=ratio,金额可统一为人民币数值; - 返回来源文件、表格行号、原始单元格、类型化数值和可追踪 citation。
The default entry point is a deterministic demonstration with no API key, vector database, or external model dependency. It extracts metadata, filters documents, preserves table schemas, retrieves relevant rows, normalizes typed cells, and returns traceable evidence within the filtered candidate set.
Requires Python 3.9 or later.
python main.py也可以传入自己的查询:
python main.py "示例成长基金2023年第四季度债券投资占基金总资产比例是多少?"示例输出:
documents_before_filter: 3
metadata_filters: QueryFilters(fund_name='示例成长基金', year=2023, period='Q4', report_type='quarterly')
documents_after_filter: 1
results:
- block_type=table source=示例成长基金2023年第4季度报告.md
table_row: {'项目': '债券投资', '占基金总资产比例': '24.80%'}
typed_values: {'占基金总资产比例': {'raw': '24.80%', 'value': 0.248, 'unit': 'ratio'}}
citation: 示例成长基金2023年第4季度报告.md#table-row-2
运行最小测试:
python -m unittest discover -s tests -vexamples/reports.json small synthetic fund-report examples
src/finagent/models.py metadata, block and search-result contracts
src/finagent/metadata.py filename/query metadata extraction
src/finagent/chunking.py schema-preserving text/table block construction
src/finagent/retrieval.py metadata filtering, row retrieval and typed-cell parsing
tests/test_prototype.py deterministic behavior checks
main.py runnable archive demo
notebooks/finAgent.ipynb historical exploration notebook
src/agent/ historical Agent/tool experiment
src/processing/ historical DOCX parsing experiment
src/retrieval/ historical LangChain retrieval experiment
src/finagent/ 和 main.py 是归档版本的清晰展示入口。其余目录保留了早期 LangChain、Agent
工具、DOCX 解析和 SelfQueryRetriever 实验,依赖旧接口和外部模型配置,不属于当前 Quick Demo。
src/finagent/ and main.py form the maintained archive demonstration. The other directories preserve
the earlier LangChain and tool experiments for historical context and are not part of the default demo.
普通向量检索会让所有报告共同参与相似度竞争,但金融查询往往已经明确包含基金名称和报告期。 先应用结构化过滤具有三个直接作用:
- 缩小候选集合;
- 避免相邻季度或名称相似基金相互干扰;
- 让最终证据来源更容易解释。
Vector similarity alone can mix reports from adjacent quarters or similarly named funds. Metadata-first retrieval uses explicit constraints before ranking content, making the candidate set smaller and the evidence path easier to explain.
项目不把表格只当作一段特殊 Markdown。表格进入独立结构化路径:
table block
-> schema (column names)
-> rows and cells
-> table-level ranking
-> row-level metric matching
-> typed cell normalization
-> source#table-row-N citation
这种处理保留:
- 表头与数值的对应关系;
- 同一行中项目与比例/金额的对应关系;
- 表格来源、基金名称和报告期;
- 原始显示值和适合计算的标准化值;
- 回答依据所在的具体表格行。
例如,系统不会只返回包含“债券投资”的整张表,而是返回:
{
"row": {"项目": "债券投资", "占基金总资产比例": "24.80%"},
"typed_value": {"value": 0.248, "unit": "ratio"},
"citation": "示例成长基金2023年第4季度报告.md#table-row-2"
}Tables are represented with explicit schemas and rows. Retrieval first selects a table, then matches the most relevant metric row, normalizes typed cells, and returns a row-level citation. This is more precise than embedding a serialized table as one undifferentiated text chunk.
早期实验还探索过:
- 基于 LangChain 的 ReAct-style tool routing;
- 基金公告 RAG 问答;
- 简单数值计算;
- JSON 结构化信息抽取;
- 条形图、饼图和折线图生成;
- DOCX 段落、图片和表格解析;
- Self-query retrieval 与 Chroma 向量库。
这些代码用于记录当时的探索方向,但没有被包装成当前可运行、可评测的完整金融 Agent。
The historical code records experiments with tool routing, document QA, calculation, JSON extraction, chart generation, DOCX parsing, self-query retrieval, and Chroma. It is preserved as an early prototype, not presented as a complete production system.
-
示例报告为合成数据,不代表真实基金公告。
-
默认排序是轻量确定性规则,不等同于完整语义检索或经过训练的 ranking model。
-
项目没有提供金融问答准确率、生产延迟或真实用户评测。
-
历史 LangChain 代码依赖旧接口和外部模型配置,可能无法在现代环境中直接运行。
-
当前只实现单表行级检索和基础数值类型化,不代表已经解决跨表关联、多级表头或复杂公式推理。
-
本项目不提供投资建议,不应用于金融决策或真实交易。
-
The examples are synthetic and do not represent real fund reports.
-
The default ranker is deterministic and lightweight, not a trained semantic ranking model.
-
No maintained financial-QA benchmark or production evaluation is provided.
-
Historical LangChain code may not run with current APIs.
-
The prototype covers single-table row retrieval and basic typed values, not multi-table joins, hierarchical headers, or complex numerical reasoning.
-
This project must not be used for financial advice or investment decisions.
This repository is preserved as an early 2024 Agent/RAG exploration and is no longer actively developed.
本仓库作为 2024 年早期 Agent/RAG 思路记录保留,不再进行功能扩展或长期维护。
MIT License. See LICENSE.