@jerryjliu0: 我们构建了一个用于尽职调查的AI代理,带有精确到源页面的审计追踪,您可以将其作为模板使用…

X AI KOLs Following 工具

摘要

LlamaIndex的Jerry Liu演示了如何使用LiteParse构建一个财务尽职调查AI代理。LiteParse是一个免费的开源PDF解析器,能够提供精确引用和边界框坐标,从而在代理工作流中实现信任和透明度。

我们构建了一个用于尽职调查的AI代理,带有精确到源页面的审计追踪,您无需为PDF解析支付任何费用即可将其作为模板使用。 秘诀在于LiteParse——我们免费、开源、无需模型的文档解析器。它能够从具有复杂布局和表格的财务文档中提取文本,并返回描述源文本中精确边界框的引用。 作为一个免费的开源解析器,它非常强大,是代理工作流中的关键组成部分! 在此查看我们的完整博客文章:https://llamaindex.ai/blog/building-a-financial-due-diligence-agent-with-liteparse?utm_medium=socials&utm_source=twitter&utm_campaign=2026-may-…
查看原文
查看缓存全文

缓存时间: 2026/05/20 20:35

我们构建了一个用于尽职调查的AI代理,具备精确到源页面的审计追踪功能,你可以将其作为模板使用,而无需为PDF解析支付一分钱。秘诀在于LiteParse——我们免费、开源、无模型的文档解析器。它能够从具有复杂布局和表格的金融文档中提取文本,并返回描述源文本中精确边界框的引用。作为一个免费的开源解析器,它功能极其强大,是智能代理工作流的关键组成部分!查看我们的完整博客文章:https://llamaindex.ai/blog/building-a-financial-due-diligence-agent-with-liteparse?utm_medium=socials&utm_source=twitter&utm_campaign=2026-may-…


如何使用LiteParse构建金融尽职调查代理

来源:https://www.llamaindex.ai/blog/building-a-financial-due-diligence-agent-with-liteparse?utm_medium=socials&utm_source=twitter&utm_campaign=2026-may-

金融尽职调查是金融领域文档最密集的工作流程之一。分析师将高达70%的时间花在手动数据提取上。这意味着时间耗费在了将PDF转录到电子表格、映射总账科目以及核对试算平衡表上。一笔交易可能涉及数百页的SEC文件,每个数字都需要有出处。我构建了一个演示应用来解决这个问题:一个AI代理,它能够吸收SEC文件,在文件间进行搜索,并通过精确的引用回答问题,这些引用会高亮显示原始PDF页面上的确切源文本。关键成分是LiteParse(https://www.npmjs.com/package/@llamaindex/liteparse),它可以从PDF中提取文本以及边界框坐标。利用这些数据,应用能够直观地高亮显示具体数字的来源,为代理的回答增加信任和透明度。在这篇文章中,我将介绍该项目的运行方式以及沿途做出的关键设计决策。

架构

该应用是一个Next.js项目,包含三层:

  1. Next.js聊天界面和PDF引用查看器
  2. 用于聊天(LLM + 工具调用)、文档摄取、SEC EDGAR集成和引用解析的API路由
  3. 一个包含三个文件/职责的核心库:PDF解析(ingest.ts)、带搜索功能的文档存储(store.ts)以及代理工具定义(tools.ts

整个代码库大约600行库代码。明确地说,我避免了使用向量数据库、嵌入管道或任何超出LLM API密钥的外部基础设施。这种简洁性使得该项目易于理解和扩展,同时展示了LiteParse的核心用法。

第一步:使用LiteParse解析PDF

使用LiteParse进行摄取非常简单。输入PDF文件路径(或文件缓冲区),它会返回结构化数据:所有文本以及每段文本的边界框坐标(xywidthheight)、字体名称和字号。

import { LiteParse } from "@llamaindex/liteparse";

const parser = new LiteParse({
  outputFormat: "json",
  ocrEnabled: false
});

export async function ingestPdf(filePath: string, filename: string) {
  const result = await parser.parse(filePath, true);
  const pages = result.json?.pages.map((pg) => ({
    pageNum: pg.page,
    width: pg.width,
    height: pg.height,
    text: pg.text,
    textItems: pg.textItems.map((item) => ({
      text: item.text,
      x: item.x,
      y: item.y,
      width: item.width,
      height: item.height,
      fontName: item.fontName,
      fontSize: item.fontSize,
    })),
  })) ?? [];
  return { filename, pages };
}

来源(https://github.com/logan-markewich/liteparse-financial-agent/blob/main/lib/ingest.ts)

大多数PDF解析器会输出文本或markdown,而LiteParse则提供文本加上布局,每个单词及其在页面上的精确位置。这正是后续实现引用高亮的关键。一份典型的10-K文件(70-100+页)只需几秒即可解析完成。

第二步:一个简单的文档存储

解析后的文档以平面JSON文件存储。

export function addDocument(doc: Document): void {
  const docs = loadStore();
  const existing = docs.findIndex((d) => d.filename === doc.filename);
  if (existing >= 0) {
    docs[existing] = doc;
  } else {
    docs.push(doc);
  }
  fs.writeFileSync(STORE_PATH, JSON.stringify(docs, null, 2));
}

来源(https://github.com/logan-markewich/liteparse-financial-agent/blob/0b0cf8fdf6b2b62611dfc330651bae9938635a5b/lib/store.ts#L64)

对于搜索,我选择了关键字匹配而非向量相似性。搜索函数接收一个查询,将其拆分为词项,并按照每个页面包含的词项数量进行评分:

const terms = query.toLowerCase().split(/\\s+/);
for (const doc of docs) {
  for (const page of doc.pages) {
    const textLower = page.text.toLowerCase();
    const score = terms.filter((t) => textLower.includes(t)).length;
    if (score === 0) continue;
    // ... 构建片段,添加到结果中
  }
}

来源(https://github.com/logan-markewich/liteparse-financial-agent/blob/0b0cf8fdf6b2b62611dfc330651bae9938635a5b/lib/store.ts#L101)

还提供了一种正则表达式模式,用于代理需要更精确的模式匹配时(例如,\\\\$[\\\\d,]+\\\\s*million 来查找金额)。为什么不用向量搜索?通常,此应用中的文档工作集很小(1-100份文件)。正如我们稍后将看到的,暴露给代理的工具足以在不使用语义搜索的情况下找到相关信息。由于10-K等文件在LLM训练数据中非常普遍,我们可以利用已有知识来识别关键术语和结构。

第三步:为代理提供工具

代理通过Vercel AI SDK(https://sdk.vercel.ai/docs)获取三个工具。工具定义使用Zod模式,结果如下所示:

function list_document() => [...]
function search_documents(query: string, file_glob: string | null, max_results: number, use_regex: boolean) => [...]
function get_page(filename: string, page_num: number) => string

来源(https://github.com/logan-markewich/liteparse-financial-agent/blob/main/lib/tools.ts)

search_documents工具中的file_glob参数允许代理将搜索范围限定到特定文档(例如,*2024*),这在加载了多份文件并需要跨期间比较时非常有用。

第四步:聊天路由

聊天端点使用Vercel AI SDK的streamText并调用工具。系统提示告诉模型已加载了哪些文档以及如何使用引用:

const result = streamText({
  model: anthropic("claude-sonnet-4-20250514"),
  system: buildSystemPrompt(),
  messages: await convertToModelMessages(messages),
  tools,
  stopWhen: stepCountIs(30),
  experimental_transform: smoothStream({
    chunking: "word"
  }),
});

来源(https://github.com/logan-markewich/liteparse-financial-agent/blob/main/app/api/chat/route.ts)

系统提示对引用格式有明确要求。它要求模型将引用的数据包裹在带有精确文件名和页码的<citation>标签中:

<citation filename="aapl-20241025-10k.pdf" page="42">394,328</citation>

最重要的是,它坚持使用原文文本:<citation>标签内的文本必须严格从文档中复制。” 应用依赖于此,因为引用系统需要在该页面上找到该确切字符串以计算高亮位置。如果LLM对数字进行转述或重新格式化,匹配将失败,最终得到未经验证的引用。在我的测试中,LLM通常能很好地遵循这些指令。当引用找不到时,通常是由于难以处理的奇怪格式差异。

第五步:引用系统

当UI在代理的响应中遇到<citation>标签时,它会执行以下操作:

  1. 解析标签以提取文件名、页码和引用短语
  2. 调用/api/cite,该接口使用findTextLocation()在页面上定位该短语
  3. 通过将匹配的字符映射回原始文本项及其坐标来计算边界框
  4. 使用LiteParse的screenshot()方法渲染PDF页面,并在精确位置绘制高亮覆盖层

匹配采用分层策略,因为LLM并不总是完全按原文输出,并且金融文档中存在一些边缘情况。匹配算法依次尝试以下策略:

  1. LiteParse的searchItems——LiteParse内置的搜索算法。尝试处理自动换行和其他细微不一致。
  2. 空格灵活的正则表达式——容忍LLM输出和PDF文本之间的格式差异。
  3. 货币/符号剥离——处理LLM添加或删除$符号的情况。
  4. 仅字母数字匹配——最后手段,忽略所有标点符号。
  5. 最长标记匹配——如果所有方法都失败,找到最独特的数字或单词。

如果找到匹配,边界框会在重叠的文本项之间按比例计算。然后利用LiteParse的截图功能,我们可以渲染带有适当文本高亮的截图。

当引用无法验证时,UI会显示一个黄色的“未验证”徽章,而不是隐藏它。这样,用户至少可以看到代理打算从哪里提取信息,即使精确匹配失败。在大多数情况下,匹配确实在页面上,只是算法无法找到(例如,$52.00B 对比 52 billion)。

第六步:SEC EDGAR集成

为了使演示独立运行,我添加了直接的SEC EDGAR集成。流程如下:

  1. 用户输入股票代码(例如,AAPL
  2. 应用通过SEC的公司代码文件将该股票代码解析为CIK编号
  3. 从EDGAR提交API获取最近的文件
  4. 用户选择要下载的文件
  5. 下载文件文档,使用LiteParse解析,添加到存储中

EDGAR API似乎返回HTML和PDF文档的混合。虽然LiteParse无法解析HTML,但应用会使用Puppeteer将HTML转换为PDF。这意味着无论原始格式如何,相同的提取管道都能工作。

这个演示不是什么

这是一个演示,而非生产系统。但要在生产环境中部署,我只会替换以下几项:

  • 将磁盘存储替换为S3或类似的blob存储,用于存储解析后的文档
  • 将平面JSON文件存储替换为带有搜索索引的适当数据库
  • 添加用户身份验证和访问控制

但这些都是在应用现有核心功能之上的工程细节。如果你复刻该仓库并添加了其中的一些内容,欢迎分享回来!

亲自尝试

完整源代码在GitHub上。你需要Node.js 18+和一个Anthropic API密钥。

git clone
cd liteparse-financial-agent
npm install
cp .env.example .env
# 在.env中添加你的ANTHROPIC_API_KEY
npm run dev

打开localhost:3000,在EDGAR标签页中搜索股票代码或上传文件,然后开始提问。

LlamaIndex 🦙 (@llama_index): 金融分析师约70%的时间花在从PDF中提取数字上。 我们构建了一个演示代理,它能够吸收SEC文件,并通过精确的引用回答问题,这些引用在原始PDF页面上高亮显示。

约600行Next.js代码。无需向量数据库。只需LiteParse。

相似文章