Skip to content

Day 1:文档解析 Pipeline——读得懂,才分析得了

为什么这个项目值得你花5天

项目一你做了一个客服 Agent——输入一句话,输出一句话。流程简单,核心是"问答"。 什么这个项目值得你花5天项目一你做了一个客服 Agent——输入一句话,输出一句话。流程简单,核心是"问答"。

项目二不同。你要让 Agent 读文档。

听起来很简单对吧?但想想:PDF 里表格嵌在段落间,Word 里标题层级乱七八糟,合同里甲方乙方混在一起没有任何标记。人看着一目了然,机器看着就是一堆字符——不是"读",是"猜"。

这五天的递进逻辑和项目一完全不同。项目一是"让 Agent 变聪明",项目二是"让 Agent 变能干"——不是回答一个问题,而是处理一批任务。

今天做什么

一个最简版本:读取 TXT 文件,解析出文字内容,统计字数,预览开头。

为什么从最简单的 TXT 开始?因为你要先确认"解析管道"是通的。就像一个水管工,先拧开第一个阀门看看水能不能流到龙头——水通了,再考虑添加过滤、加热、分流这些高级功能。

你需要什么

  • Python 3.10+
  • 一个文本编辑器
  • 不需要 API Key、不需要联网、不需要花钱

📦 本项目全程使用的框架版本:

框架版本首次用到
langchain≥0.3Day 1
langchain-community≥0.3Day 1
pydantic≥2.0Day 2
mcp0.9.xDay 5
streamlit≥1.28Day 6

每天会在对应章节给出具体安装命令,不用第一天全部装完。

bash
pip install langchain langchain-community

📁 代码目录

doc_analyzer/
└── day1.py        ← 唯一一个文件,40行

代码

python
# day1.py — 文档解析基础链路

import os

# 准备测试文档(如果没有的话自动创建)
TEST_DOC = "sample_contract.txt"
if not os.path.exists(TEST_DOC):
    with open(TEST_DOC, "w", encoding="utf-8") as f:
        f.write("""合作协议

甲方:北京科技有限公司
乙方:上海创新技术有限公司

第一条 合作内容
甲乙双方就人工智能技术研发达成合作,共同开发智能客服系统。

第二条 合作期限
本协议有效期自2025年1月1日起至2027年12月31日止。

第三条 知识产权
合作期间产生的知识产权归双方共同所有。

第四条 保密条款
双方应对合作中获知的对方商业机密予以保密。

签署日期:2025年1月1日
""")

print(f"📄 测试文档已准备: {TEST_DOC}")

# ===== 文档解析Pipeline =====
from langchain_community.document_loaders import TextLoader

class DocumentPipeline:
    """文档处理流水线"""
    
    def __init__(self):
        self.documents = []
    
    def load_document(self, filepath: str) -> list:
        """加载文档"""
        print(f"📂 加载文档: {filepath}")
        loader = TextLoader(filepath, encoding="utf-8")
        docs = loader.load()
        print(f"   ✅ 加载成功,{len(docs)} 个文档块")
        return docs
    
    def preview(self, docs: list, max_chars: int = 150):
        """预览文档前N个字"""
        for i, doc in enumerate(docs):
            content = doc.page_content[:max_chars]
            char_count = len(doc.page_content)
            print(f"\n📝 文档块 {i+1} ({char_count}字):")
            print(f"   {content}...")
            print(f"   ---")
    
    def get_stats(self, docs: list) -> dict:
        """获取文档统计信息"""
        total_chars = sum(len(d.page_content) for d in docs)
        return {
            "文件数": 1,
            "文档块数": len(docs),
            "总字数": total_chars,
        }

# ===== 运行 =====
pipeline = DocumentPipeline()
docs = pipeline.load_document(TEST_DOC)
pipeline.preview(docs)
stats = pipeline.get_stats(docs)

print(f"\n📊 文档统计:")
for key, value in stats.items():
    print(f"   {key}: {value}")

运行

bash
python day1.py

你应该看到:

📄 测试文档已准备: sample_contract.txt
📂 加载文档: sample_contract.txt
   ✅ 加载成功,1 个文档块

📝 文档块 1 (183字):
   合作协议

甲方:北京科技有限公司
乙方:上海创新技术有限公司
...
   ---

📊 文档统计:
   文件数: 1
   文档块数: 1
   总字数: 183

你学到了什么

TextLoader 是 LangChain 里最基础的文档加载器。它做的事很简单——读文件、返回文档对象。但你要理解它输出的结构:

每个 Document 对象有两个核心属性:page_content(文档正文)和 metadata(元信息,比如文件路径)。LangChain 的所有文档处理工具,输入输出都是这个结构——这跟项目一里 HumanMessage/AIMessage 是统一的消息格式,道理一样。

解析不是"读文件"。 读文件只是把字符加载到内存,解析是理解文档结构。TextLoader 做了最简单的一步——把整个 TXT 文件当作一个文档块。明天开始,我们要让 Agent 理解:这个文件分几条、每条讲什么、甲方乙方分别是谁。

明天的预告

今天水龙头通了。明天用 LCEL 管道 搭一条分析链:文档进去 → Prompt 加工 → LLM 理解 → Pydantic 结构化输出。把杂乱无章的合同文本变成一个整整齐齐的 JSON 对象。


Day 1 完成。Pipeline 跑通了——能读文档,能预览,能统计。地基对了。