Day 6:Streamlit 部署 + 项目二总结
今天做什么
前五天你的文档分析能力已经很完整了——解析、提取、并发、缓存、MCP 服务化。但还差最后一步:让非技术人员也能用。 天做什么前五天你的文档分析能力已经很完整了——解析、提取、并发、缓存、MCP 服务化。但还差最后一步:让非技术人员也能用。
不是所有人都能打开终端敲 python doc_analyzer_server.py。产品经理、法务、HR——他们需要的是一个"上传文件,点按钮,看结果"的界面。
今天用 Streamlit 做这件事。Streamlit 是 Python 生态里最快的 Web UI 框架——你不需要学 HTML/CSS/JavaScript,全部用 Python 写。
你需要安装
bash
pip install streamlit📁 代码目录
doc_analyzer/
├── sample_contract.txt
├── day1.py
├── day2.py
├── day3.py
├── day4.py
├── doc_analyzer_server.py ← Day5 的 MCP Server
├── app.py ← 新增!Streamlit Web界面
└── test_mcp.py ← Day5 的测试脚本代码
python
# app.py — Streamlit 文档分析前端
import streamlit as st
# ===== 页面设置 =====
st.set_page_config(
page_title="文档分析助手",
page_icon="📄",
layout="wide"
)
st.title("📄 文档分析助手")
st.caption("上传文档,自动提取关键信息、生成摘要、分类归档")
# ===== 侧边栏:分析选项 =====
with st.sidebar:
st.header("⚙️ 分析选项")
enable_summary = st.checkbox("生成摘要", value=True)
enable_classify = st.checkbox("自动分类", value=True)
enable_contract = st.checkbox("合同分析(提取甲乙方等)", value=True)
st.divider()
st.caption("💡 支持格式:TXT / PDF / DOCX(当前演示版支持 TXT)")
# ===== 主区域:文件上传 =====
uploaded_file = st.file_uploader(
"拖拽文件到这里,或点击上传",
type=["txt", "pdf", "docx"],
help="支持 TXT、PDF、DOCX 格式"
)
if uploaded_file is not None:
# --- 读取文件内容 ---
try:
text_content = uploaded_file.read().decode("utf-8", errors="ignore")
except Exception as e:
st.error(f"无法读取文件:{e}")
st.stop()
# --- 显示文档原文(可折叠)---
with st.expander("📝 查看原文", expanded=False):
st.text_area("文档内容", text_content, height=250, disabled=True)
# --- 文档基础统计 ---
col1, col2, col3 = st.columns(3)
col1.metric("📏 文档字数", len(text_content))
col2.metric("📄 文件大小", f"{len(text_content.encode('utf-8')) / 1024:.1f} KB")
col3.metric("📂 文件名", uploaded_file.name)
st.divider()
# --- 开始分析按钮 ---
if st.button("🔍 开始分析", type="primary", use_container_width=True):
results_container = st.container()
with results_container:
# 默认分类(即使不勾选"自动分类",后续也可能用到)
category = "其他"
# 1. 分类
if enable_classify:
with st.spinner("📂 正在分类..."):
# 基于关键词的快速分类
scores = {"合同": 0, "简历": 0, "报告": 0}
if any(w in text_content for w in ["合同", "协议", "甲方", "乙方"]):
scores["合同"] += 1
if any(w in text_content for w in ["简历", "工作经历", "教育背景"]):
scores["简历"] += 1
if any(w in text_content for w in ["报告", "分析", "调研", "数据"]):
scores["报告"] += 1
top = max(scores, key=scores.get)
category = top if scores[top] > 0 else "其他"
st.success(f"📂 文档分类:**{category}**")
with st.expander("查看分类得分"):
for k, v in scores.items():
st.write(f"- {k}: {v} 分")
# 2. 摘要
if enable_summary:
with st.spinner("📄 正在生成摘要..."):
if len(text_content) <= 150:
summary = text_content
else:
summary = text_content[:150].replace("\n", " ") + " ……"
st.info(f"📄 文档摘要:\n{summary}")
# 3. 合同分析
if enable_contract and category == "合同":
with st.spinner("📋 正在分析合同..."):
# 提取甲乙方等关键信息
contract_info = []
for line in text_content.split("\n"):
line = line.strip()
if line.startswith("甲方"):
contract_info.append(f"- 🔵 {line}")
elif line.startswith("乙方"):
contract_info.append(f"- 🟠 {line}")
elif "期限" in line or "有效期" in line:
contract_info.append(f"- 📅 {line}")
elif "知识产权" in line:
contract_info.append(f"- ⚖️ {line}")
if contract_info:
st.success("📋 合同关键信息:")
for info in contract_info:
st.markdown(info)
else:
st.warning("未检测到明显的合同格式信息")
st.divider()
st.success("✅ 分析完成!")
st.caption("提示:以上是基于规则的演示分析。完整版本调用后端 MCP Server 获取更精准的结果。")
# ===== 空状态 =====
else:
st.info("👆 请上传一份文档开始分析")
# 示例按钮
st.divider()
st.caption("没有文档?试试这个示例:")
if st.button("📋 加载示例合同"):
sample = """合作协议
甲方:北京科技有限公司
乙方:上海创新技术有限公司
第一条 合作内容
甲乙双方就人工智能技术研发达成合作,共同开发智能客服系统。
第二条 合作期限
本协议有效期自2025年1月1日起至2027年12月31日止。
第三条 知识产权
合作期间产生的知识产权归双方共同所有。
第四条 保密条款
双方应对合作中获知的对方商业机密予以保密。
签署日期:2025年1月1日"""
st.session_state["sample_text"] = sample
st.text_area("示例合同内容", sample, height=250)运行
bash
streamlit run app.py浏览器会自动打开 http://localhost:8501。
你应该看到:
- 一个干净的 Web 界面,中间是上传区域
- 上传文件后,左边显示统计(字数、文件大小),右边显示分析结果
- 尝试上传
sample_contract.txt——分类、摘要、合同分析三个模块依次呈现
项目二总结
从"读一个 TXT 文件"到"一个能处理上百份文档的 Web 服务"——这就是这六天的旅程。
| 天 | 核心 | 你掌握了 |
|---|---|---|
| Day 1 | 文档加载 Pipeline | TextLoader,文档预览,字数统计——让 Agent 能"读"文档 |
| Day 2 | LCEL 结构化提取 | prompt | llm | parser 管道,Pydantic 定义输出格式 |
| Day 3 | asyncio 并发处理 | asyncio.gather() 批量并发,50 份文档同时分析,提速近 10 倍 |
| Day 4 | 分析缓存 | SHA256 哈希判重,缓存命中跳过分析——已跑过的不重跑 |
| Day 5 | MCP 标准化 | 把分析能力包装成 MCP Server,任何客户端都能调用 |
| Day 6 | Streamlit 部署 | Web 界面,非技术人员也能用。上传文档,点按钮,看结果 |
跟项目一的对照
现在你手上有两个完整的 Agent 项目了。看一眼它们的对比:
| 维度 | 项目一:智能客服 | 项目二:文档分析 |
|---|---|---|
| 核心任务 | 回答用户问题 | 分析文档内容 |
| Agent 输入 | 一句话(用户消息) | 一个文件(文档) |
| Agent 输出 | 一句话(回复) | 结构化数据(JSON/分类/摘要) |
| 并发场景 | 多用户同时对话 | 批量文档同时分析 |
| 状态管理 | LangGraph + MemorySaver | 缓存 + Store |
| 关键技术 | StateGraph / Checkpoint / MCP | LCEL / asyncio / MCP / Streamlit |
两个项目用到的核心技术栈高度重合——这就是反复练习的价值。你现在看 LangChain 的文档、看 MCP 的协议规范、看 asyncio 的用法,已经不会"看不懂"了——因为你亲手用过了。
目二的天花板
今天你做的分析,主要靠关键词匹配。但真实的文档分析系统可以做得更多:
- 语义理解:用向量搜索找到"跟这条相似的其他条款"(项目一 Days 3-4 的 RAG)
- 多格式支持:PDF 里的表格、Word 里的批注、扫描件的 OCR 识别
- 版本对比:同一份合同 v1 和 v2 改了哪里,自动高亮
- 风险识别:自动标记合同中的"无限期责任""不设上限的违约金"等高危条款
这些虽然今天没做,但你已经有了地基。加一个功能 = 加一个工具 = 在 MCP Server 里多注册一个端——你会的套路是一样的。
🎉 项目二完成。Agent 能读文档、分析内容、并发处理上百份、缓存去重、MCP 服务化、Web 部署。从 TXT 到 Web——你走完了从"脚本"到"产品"的完整路径。

