乌鲁木齐市网站建设_网站建设公司_后端开发_seo优化
2026/1/16 20:48:03 网站建设 项目流程

无代码,纯调试总结。


实现知识助手的 app.py 关键信息摘要

本文档总结 app.py 关键信息摘要

本文档总结了 app.py 脚本的核心组件、工作流程和使用的模型。

1. 核心技术栈

  • Web 框架: Streamlit - 用于构建交互式 Web UI。
  • 向量数据库: ChromaDB - 以持久化模式 (PersistentClient) 运行,数据存储在本地的 ./my_db 文件夹中。
  • PDF 解析库: PyPDF (PdfReader) - 用于从 PDF 文件中提取纯文本内容。注意:此版本无法处理图片或扫描件中的文字。
  • AI 客户端: OpenAI - 作为 API 端点交互的客户端。

2. 使用的 AI 模型及服务

  • API 端点: https://api.**********.com/llm/v1
  • Embedding 模型: qwen3-embedding-8b - 用于将文本(文档片段和用户提问)转换为向量。
  • 聊天生成模型: glm-4.7 - 用于根据检索到的上下文和用户问题生成最终答案。

3. 工作流程 (RAG)

应用包含两个主要的工作流程:

A. 数据入库流程 (当点击“开始处理入库”时)

  1. 读取 PDF: 使用 extract_text_from_pdf 函数,通过 PdfReader 逐页提取文本。
  2. 文本切分: 使用 split_text_into_chunks 函数将完整的文本内容切分成大小约 500 字符、重叠 50 字符的片段。
  3. 向量化: 遍历每一个文本片段,调用 get_embedding 函数(使用 qwen3-embedding-8b 模型)生成向量。
  4. 存入数据库: 使用 collection.add() 方法,将文本片段、对应的向量和 ID 批量存入 ChromaDB 的 manual_docs 集合中。

B. 问答检索流程 (当用户在聊天框提问时)

  1. 捕获问题: 通过 st.chat_input 获取用户输入的 prompt
  2. 问题向量化: 调用 get_embedding 函数将用户的 prompt 转换为一个查询向量 q_vec
  3. 数据库检索: 使用 collection.query() 方法,传入查询向量 q_vec,在数据库中查找最相似的 5 个文本片段。
  4. 构建上下文: 将检索到的 5 个文本片段组合成一个完整的上下文 best_context
  5. 生成答案: 调用 client_ai.chat.completions.create 方法(使用 glm-4.7 模型),将历史聊天记录、best_context 和用户问题一起发送给大模型,以流式(打字机效果)生成并显示答案。
  6. 保存记录: 将用户的提问和 AI 的回答存入 st.session_state.messages 中,以实现多轮对话记忆。

4. 关键函数

  • init_db(): 初始化并缓存 ChromaDB 的连接。
  • extract_text_from_pdf(): 负责读取 PDF 文件。
  • split_text_into_chunks(): 负责将长文本切片。
  • get_embedding(): 负责调用 Embedding 模型生成向量。

app_with_ocr.py 升级摘要

app_with_ocr.pyapp.py 的一个重大升级版本,核心目标是解决原版本无法处理 PDF 中图片和扫描页的问题。

1. 核心技术栈变更

  • PDF 解析库升级:

    • : PyPDF (PdfReader)
    • 升级为: PyMuPDF (fitz)
    • 原因: PyMuPDF 提供了强大的功能,不仅能提取文本,还能从 PDF 页面中提取图片数据,这是实现 OCR 的基础。
  • 新增图像处理能力:

    • 引入 Pillow (PIL): 用于将 PyMuPDF 提取出的原始图片字节流转换为可处理的图片对象。
    • 引入 pytesseract: 作为 Python 连接 Tesseract OCR 引擎(需要安装并启动.exe)的桥梁,负责将图片对象中的文字识别出来。
    • 引入 time: 用于监控和计算 Tesseract OCR 过程的耗时,便于调试。

2. 数据入库流程的重大改进

数据入库的核心函数 extract_text_from_pdf 被完全重构为 extract_text_from_pdf_with_ocr,采用了更先进的“文本与图片均处理”策略。

新的提取流程 (逐页进行):

  1. 总是先提取直接文本: 使用 page.get_text() 提取页面上所有可选中的文本。
  2. 总是再提取图片: 无论上一步是否提取到文本,程序都会继续使用 page.get_images() 查找当前页的所有图片。
  3. 调用 OCR: 对找到的每一张图片,执行以下操作:
    a. 启动监控: 打印日志并开始计时。
    b. 调用 Tesseract: 使用 pytesseract.image_to_string() 对图片进行文字识别。
    c. 结束监控: 打印 OCR 过程的耗时,并根据识别结果(成功、无文字、失败)输出详细的诊断日志。
  4. 合并内容: 将该页的“直接文本”和所有图片的“OCR 结果”合并为该页的最终文本内容。

这个新策略解决了原版本最大的痛点:

  • 支持扫描件: 能够处理完全由图片组成的 PDF 页面。
  • 支持图文混合页: 能够同时提取一页中的普通文本和图片中的文字,避免了信息丢失。

3. 关键函数变更

  • extract_text_from_pdf() 被替换为 extract_text_from_pdf_with_ocr(),实现了上述的全新提取逻辑。
  • 其他核心函数(init_db, split_text_into_chunks, get_embedding)和问答检索流程保持不变,展现了良好代码架构的模块化优势。

app_with_vlm.py 升级摘要

app_with_vlm.py 是对 app_with_ocr.py 的终极进化,它用一个强大的多模态视觉语言模型 (VLM) 替换了传统的 OCR 引擎,实现了从“文字识别”到“图像理解”的跨越。

1. 核心技术栈与模型变更

  • 引入视觉语言模型 (VLM):

    • 这是本次升级的核心。应用现在引入了一个新的 AI 模型角色:“图像分析师”。
    • 新增模型: 一个支持视觉功能的聊天模型(代码中占位符为 gpt-4-vision-preview)。注意:实际模型名称需根据 API 服务提供方确认。
    • 目的: 不再是简单地识别图片中的字符,而是能够理解、分析和描述复杂的图片内容,如时序图、架构图、流程图等。
  • 技术替换:

    • : pytesseract
    • 升级为: 直接调用支持视觉的 client_ai.chat.completions.create API
    • 原因: VLM 的能力远超 OCR,能提供对图片内容的深度理解和文字描述,而不仅仅是提取字符。
  • 新增辅助库:

    • 引入 base64: 用于将图片数据编码成 Base64 字符串,这是通过 JSON 将图片传递给 VLM API 的标准格式。

2. 数据入库流程的终极形态

此版本采用了“文本化存储”策略,将所有非文本信息(图片、图表)都预处理成高质量的文本描述,再存入知识库。

新的提取流程 (逐页进行):

  1. 提取直接文本: 流程不变,首先提取页面上的可选中文本。
  2. 提取图片: 流程不变,接着提取页面上的所有图片。
  3. 调用 VLM 进行图像理解 (关键变更):
    a. 对找到的每一张图片,调用新增的 describe_image_with_vlm 函数。
    b. 在该函数内部,图片被编码为 Base64,并连同一个描述任务的 Prompt (例如:“详细描述这张图片的内容...”) 发送给 VLM 模型。
    c. VLM 返回对图片的详细文字描述。
  4. 合并内容: 将该页的“直接文本”和 VLM 生成的“图片描述”文本(用 [图片描述开始/结束] 标签包裹以区分)合并为该页的最终内容。

这个新策略的优势是:

  • 理解复杂信息: 能够处理 OCR 完全无法应对的图表和流程图,将它们的内在含义转换为可检索的文本。
  • 知识的统一性: 无论原始信息是文本还是图片,最终都以高质量的文本形式存入向量数据库,简化了后续的检索流程。
  • 架构优雅: 无需改动向量数据库的结构或检索逻辑,仅在数据预处理阶段引入 VLM 作为“分析师”即可。

3. 关键函数变更

  • 新增 describe_image_with_vlm(): 这是一个全新的函数,封装了调用视觉大模型进行图片分析的所有逻辑。
  • extract_text_from_pdf_with_ocr() 再次进化: 其内部的图片处理逻辑由调用 pytesseract 变更为调用 describe_image_with_vlm()

至此,该应用已从一个简单的文本问答助手,演进为一个能够深度理解图文混合文档的、真正的多模态知识库问答系统


app_with_vlm.py 最终优化版解析

app_with_vlm.py 是项目的最终形态,它不仅是一个多模态知识库问答系统,更集成了多项性能和成本优化措施,使其变得高效、稳定且易于维护。

1. 核心架构:三模型分离 + 多重优化

此版本采用了先进的 “三模型分离” 架构,并在此基础上实现了 “四重优化”,是生产级 RAG 应用的典范。

  • 三模型分离架构 (Three-Model Architecture):

    • VLM 模型 (图像理解): Gemini_25_Flash,通过定制的 OpenAIAdapter 访问,负责将图片内容(如图表、流程图、UI截图)转化为详细的文本描述。
    • Embedding 模型 (文本向量化): qwen3-embedding-8b,负责将所有文本内容(原文 + 图片描述)转换为向量,用于存储和检索。
    • Chat Completion 模型 (生成答案): glm-4.7,负责基于检索到的上下文,生成最终的对话回答。
  • 四重核心优化 (Four-Layer Optimization):

    1. 文件级缓存 (File-level Caching): 首次处理PDF后,将提取的全部内容(含元数据)保存为 JSON 缓存文件。后续若文件未变,则直接从缓存加载,彻底跳过耗时的PDF解析和VLM分析过程
    2. 图像去重 (Image Deduplication): 在单次文件处理中,对每张图片计算哈希值。对于内容相同的图片,只调用一次VLM进行分析,后续直接复用结果,显著降低API调用成本和延迟
    3. API分批处理 (API Batching): 在生成 Embedding 时,将成千上万的文本块分批(例如每批100个)发送给API。这从根本上解决了 413 Request Entity Too Large 的错误
    4. 数据库分批写入 (DB Batch Ingestion): 将数据分批次写入 ChromaDB,而不是在内存中准备好所有数据后一次性写入。这极大地降低了处理大文件时的内存消耗,使应用更加稳定。

2. 知识库构建流程 (数据入库)

数据入库流程经过精心设计,整合了上述所有优化策略。

  1. 文件上传与哈希计算: 用户上传 PDF,系统计算文件内容的 SHA256 哈希值。
  2. 缓存检查: 系统根据哈希值查找对应的 .json 缓存文件。
    • 命中缓存: 直接从 JSON 文件加载已处理好的内容列表,流程跳转到第 5 步。
    • 未命中缓存: 执行完整的提取流程(第 3、4 步)。
  3. 内容提取与元数据附加 (Extract & Tag):
    • 使用 PyMuPDF (fitz) 逐页提取文本和图片。
    • 对每一份内容(文本或图片描述),都附加上元数据,例如:{"source_file": "文件名.pdf", "page_number": 5}
  4. VLM 图像理解 (核心步骤):
    • 对提取的每张图片,计算其内容的哈希值。
    • 检查内存缓存 image_cache: 如果该哈希值已存在,则直接复用描述;否则,调用 VLM 模型生成描述,并存入 image_cache
    • VLM 生成的描述同样被附加上元数据。
  5. 缓存保存: 如果本次执行了提取流程,则将包含完整元数据的内容列表写入 .json 缓存文件,供未来使用。
  6. 文本分块 (Chunking): 将所有内容(文本和图片描述)切分成更小的片段,同时确保每个片段都继承其原始的元数据
  7. 分批向量化与入库 (Batch & Ingest):
    • 启动一个循环,按 BATCH_SIZE (例如100) 对所有文本块进行迭代。
    • 在循环的每一步内,完成一小批数据的“向量生成”和“数据库写入”操作。
    • 这个“生成一点、写入一点”的模式确保了高效和低内存占用。
步骤 1/3: 提取PDF内容...任务: 这个阶段是纯粹的“阅读和分析”。它会完整地读取你上传的 PDF 文件,提取所有文本,并调用 VLM 模型去理解和描述所有的图片。
产出: 所有这些处理完的内容(文本和图片描述)会被收集到一个临时的列表变量 all_content 中。
数据库操作: 无。
步骤 2/3: 正在将内容切分成小块...任务: 接收上一步生成的 all_content 列表,然后把里面每一项的长文本(无论是原文还是图片描述)切分成适合存入数据库的小块(Chunks)。
产出: 一个包含所有小文本块的列表 chunks 和一个包含对应元数据的列表 metadatas。
数据库操作: 无。
步骤 3/3: 正在处理批次...任务: 这是唯一一个与数据库写入相关的步骤。它会循环遍历上一步生成的所有小文本块。
具体操作: 在循环的每一步里,它会:
取一小批(100个)文本块。
为这一批文本块生成向量(Embeddings)。
将这一批的文本、向量和元数据一起写入 ChromaDB 数据库。
数据库操作: 有,并且是分批次写入。

3. 问答检索流程 (RAG)

问答流程利用了强大的元数据过滤功能,实现了精确检索。

  1. 范围选择 (Scope Selection): UI上提供一个单选框,允许用户选择是在“所有文档中检索”还是在某一个特定文件内进行检索。
  2. 构建 where 过滤器: 根据用户的选择,动态构建 ChromaDB 的 where 查询条件。
    • 如果选择特定文件(如 report.pdf),则过滤器为 {"source_file": "report.pdf"}
    • 如果选择所有文档,则不使用过滤器 (None)。
  3. 问题向量化: 将用户提问通过 Embedding 模型转换为查询向量。
  4. 数据库精确查询: 调用 collection.query() 方法,同时传入查询向量where 过滤器。数据库只会从符合元数据条件的文档中查找相似片段。
  5. 生成答案与展示依据:
    • 将检索到的上下文和问题提交给 Chat 模型生成答案。
    • 在前端的“参考依据”部分,清晰地展示每个上下文片段来自哪个文件的哪一页,极大地提升了答案的可信度和可追溯性。

4. 关键函数与设计变更

  • extract_text_from_pdf_with_ocr():

    • VLM 提示词 (Prompt): 内含一个为电气、通信、测试和用户操作手册领域深度定制的、高度优化的提示词。它指导 VLM 扮演领域专家,并根据图片类型(UI截图、电路图、时序图等)执行不同的分析任务,以生成最精准、简洁的描述。
    • 图像去重: 函数内部实现了基于哈希的图像去重逻辑 (image_cache)。
    • 元数据附加: 为所有提取出的文本和图片描述附加来源文件和页码等元数据。
  • 侧边栏处理逻辑: 这是整个入库流程的核心,包含了文件缓存检查、调用提取函数、分块以及分批处理的循环。

  • split_content_into_chunks(): 被重构以支持带元数据的字典列表,确保分块后元数据不丢失。

  • 主聊天界面: 新增了 st.radio 用于范围选择,并且 collection.query 调用中增加了 where 参数以实现精确过滤。


Streamlit 用法总结

check_db.py 是一个独立的数据面板应用,用于可视化和管理 ChromaDB 数据库。它集中展示了多种 Streamlit 的核心功能和高级应用技巧。

1. 页面配置与布局 (st.set_page_config, st.title, st.divider)

  • 知识点: 使用 st.set_page_config(layout="wide") 实现宽屏布局,并通过 st.title, st.header, st.divider 等组件构建清晰的页面信息结构。
  • 应用: 脚本通过这些组件划分出“摘要”、“内容详情”、“危险操作”等区域,提供了优秀的用户视觉引导。

2. 缓存与资源管理 (@st.cache_resource)

  • 知识点: @st.cache_resource 装饰器用于缓存“重资源”(如数据库连接),避免在每次页面重载时重复创建。
  • 应用: connect_to_db 函数使用此装饰器,确保与 ChromaDB 的连接只建立一次,极大地提升了应用性能,是 Streamlit 开发的最佳实践。

3. 流程控制 (st.stop, st.rerun)

  • 知识点: st.stop() 用于在特定条件下(如数据库未就绪)中止脚本执行,防止后续代码出错。st.rerun() 用于强制刷新整个页面,以立即显示状态变更。
  • 应用:
    • 在数据库连接失败时使用 st.stop() 进行优雅的错误处理。
    • 在“清空数据库”操作后使用 st.rerun() 强制刷新 UI,提供即时反馈。

4. 交互式小组件 (st.slider, st.button, st.expander)

  • 知识点: 利用滑块 (st.slider)、按钮 (st.button) 和可折叠容器 (st.expander) 来创建丰富的用户交互体验。
  • 应用:
    • st.slider 用于让用户动态选择查看的数据条数。
    • st.expander 用于将危险的“清空”功能默认隐藏,防止误操作。
    • st.button 用于触发操作。

5. 数据展示 (st.metric, st.dataframe)

  • 知识点: st.metric 用于突出显示关键指标(KPI),st.dataframe 用于将 pandas DataFrame 渲染为可交互的表格。
  • 应用:
    • 使用 st.metric 醒目地展示“知识库片段总数”。
    • 使用 st.dataframe 提供了一个可排序、可搜索的数据浏览界面,体验远超静态表格。

6. 高级交互:使用 st.session_state 实现二次确认

  • 知识点: st.session_state 是一个可以在多次页面重载之间持久化数据的类字典对象,是实现复杂、有状态交互逻辑的核心。
  • 应用: “清空数据库”的二次确认功能是 st.session_state 的经典应用。
    1. 点击“清空”按钮,将 st.session_state.confirm_delete 设为 True
    2. 页面重载后,脚本检测到此状态,从而显示最终的确认按钮。
    3. 操作完成后,将状态重置为 False 并刷新页面。
    • 这个机制完美解决了在 Streamlit 的无状态重载模型中实现多步确认流程的难题。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询