关于 document-chat-interface
用于构建文档对话界面的开发指南,让用户以自然语言查询文档。内容涵盖文档导入、检索、对话上下文和引用,并提供 LangChain、LlamaIndex 与 RAG 实现示例。
主要功能
- 01处理 PDF、代码库、邮件和网页
- 02提取、清理、分块并标注文本
- 03维护对话上下文
- 04生成带来源引用的回答
- 05支持问题改写和后续提问
适用场景
- 01为报告或研究论文构建问答
- 02以对话方式搜索邮件归档
- 03通过提问探索代码库
- 04创建可交互的公司文档资源
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ qodex-ai/ ai-agent-skills --skill document-chat-interface安装后在 Claude Code 中输入/document-chat-interface确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
examples/conversation_manager.pydocument_processors.pytext_processor.py详细介绍
文档聊天界面
构建智能聊天界面,让用户能够使用自然语言查询文档并与之互动,将静态文档转变为交互式知识源。
概述
文档聊天界面结合了三种能力:
- 文档处理 - 提取并准备文档
- 语义理解 - 理解问题并查找相关内容
- 对话界面 - 保持上下文并提供自然的回复
常见应用
- PDF 问答:回答有关研究论文、报告和书籍的问题
- 电子邮件搜索:以对话方式查找电子邮件存档中的信息
- GitHub 探索器:询问有关代码仓库的问题
- 知识库:交互式访问公司文档
- 合同审查:使用自然语言查询法律文档
- 研究助手:交互式探索学术论文
架构
Document Source
↓
Document Processor
├→ Extract text
├→ Process content
└→ Generate embeddings
↓
Vector Database
↓
Chat Interface ← User Question
├→ Retrieve relevant content
├→ Maintain conversation history
└→ Generate response
核心组件
1. 文档来源
实现示例请参见 examples/document_processors.py:
PDF 文档
- 从 PDF 页面中提取文本
- 保留文档结构和元数据
- 使用 OCR(pytesseract)处理扫描版 PDF
- 提取表格(pdfplumber)
GitHub 仓库
- 从仓库中提取代码文件
- 解析仓库结构
- 处理多种文件类型
电子邮件存档
- 提取电子邮件元数据(发件人、收件人、主题、日期)
- 解析电子邮件正文内容
- 处理多种邮箱格式
网页
- 提取页面文本和结构
- 保留标题层级
- 提取链接和导航
YouTube/音频
- 获取 YouTube 视频的文字稿
- 转录音频文件
- 处理多种格式
2. 文档处理
实现示例请参见 examples/text_processor.py:
文本提取与清理
- 移除多余的空白和特殊字符
- 使用重叠片段进行智能文本分块
- 智能检测句子边界
元数据提取
- 提取标题、作者、日期和语言
- 计算字数和文档统计信息
- 跟踪文档来源和格式
保留结构
- 在文本块中保留标题层级
- 保留章节上下文
- 支持分层检索
3. 聊天界面设计
实现示例请参见 examples/conversation_manager.py:
对话管理
- 在大小限制内保留对话历史
- 跟踪消息元数据(时间戳、角色)
- 为大模型集成提供上下文
- 按需清除历史记录
问题完善
- 补全问题中的隐含指代
- 处理代词和上下文指代
- 利用先前的上下文改善问题表述
回复生成
- 使用文档上下文回答问题
- 在提示词中保留对话历史
- 提供来源引用
- 处理超出范围的问题
4. 用户体验功能
引用与来源
def format_response_with_citations(response: str, sources: List[Dict]) -> str:
"""Add source citations to response"""
formatted = response + "\n\n**Sources:**\n"
for i, source in enumerate(sources, 1):
formatted += f"[{i}] Page {source['page']} of {source['source']}\n"
if 'excerpt' in source:
formatted += f" \"{source['excerpt'][:100]}...\"\n"
return formatted
澄清问题
def generate_follow_up_questions(context: str, response: str) -> List[str]:
"""Suggest follow-up questions to user"""
prompt = f"""
Based on this Q&A, generate 3 relevant follow-up questions:
Context: {context[:500]}
Response: {response[:500]}
"""
follow_ups = llm.generate(prompt)
return follow_ups
错误处理
def handle_query_failure(question: str, error: Exception) -> str:
"""Handle when no relevant documents found"""
if isinstance(error, NoRelevantDocuments):
return (
"I couldn't find information about that in the documents. "
"Try asking about different topics like: "
+ ", ".join(get_main_topics())
)
elif isinstance(error, ContextTooLarge):
return (
"The answer requires too much context. "
"Can you be more specific about what you'd like to know?"
)
else:
return f"I encountered an issue: {str(error)[:100]}"
实现框架
使用 LangChain
from langchain.document_loaders import PDFLoader
from langchain.text_splitter import CharacterTextSplitter
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.chat_models import ChatOpenAI
from langchain.chains import ConversationalRetrievalChain
# Load document
loader = PDFLoader("document.pdf")
documents = loader.load()
# Split into chunks
splitter = CharacterTextSplitter(chunk_size=1000)
chunks = splitter.split_documents(documents)
# Create embeddings
embeddings = OpenAIEmbeddings()
vectorstore = Chroma.from_documents(chunks, embeddings)
# Create chat chain
llm = ChatOpenAI(model="gpt-4")
qa = ConversationalRetrievalChain.from_llm(
llm=llm,
retriever=vectorstore.as_retriever(),
return_source_documents=True
)
# Chat interface
chat_history = []
while True:
question = input("You: ")
result = qa({"question": question, "chat_history": chat_history})
print(f"Assistant: {result['answer']}")
chat_history.append((question, result['answer']))
使用 LlamaIndex
from llama_index import GPTVectorStoreIndex, SimpleDirectoryReader, ChatMemoryBuffer
from llama_index.llms import ChatMessage, MessageRole
# Load documents
documents = SimpleDirectoryReader("./docs").load_data()
# Create index
index = GPTVectorStoreIndex.from_documents(documents)
# Create chat engine with memory
chat_engine = index.as_chat_engine(
memory=ChatMemoryBuffer.from_defaults(token_limit=3900),
llm="gpt-4"
)
# Chat loop
while True:
question = input("You: ")
response = chat_engine.chat(question)
print(f"Assistant: {response}")
使用基于 RAG 的方法
from sentence_transformers import SentenceTransformer
import faiss
import numpy as np
# Load and embed documents
model = SentenceTransformer('all-MiniLM-L6-v2')
documents = load_documents("document.pdf")
embeddings = model.encode(documents)
# Create FAISS index
dimension = embeddings.shape[1]
index = faiss.IndexFlatL2(dimension)
index.add(np.array(embeddings).astype('float32'))
# Chat function
def chat(question):
# Embed question
q_embedding = model.encode(question)
# Retrieve documents
k = 5
distances, indices = index.search(
np.array([q_embedding]).astype('float32'), k
)
# Get relevant documents
context = " ".join([documents[i] for i in indices[0]])
# Generate response
response = llm.generate(
f"Context: {context}\nQuestion: {question}\nAnswer:"
)
return response
最佳实践
文档处理
- ✓ 支持多种格式(PDF、TXT、docx 等)
- ✓ 高效处理大型文档
- ✓ 保留文档结构
- ✓ 提取元数据
- ✓ 处理多种语言
- ✓ 为扫描版 PDF 实现 OCR
对话质量
- ✓ 保持对话上下文
- ✓ 提出澄清问题
- ✓ 引用来源
- ✓ 处理歧义
- ✓ 建议后续问题
- ✓ 处理超出范围的问题
性能
- ✓ 优化检索速度
- ✓ 实现缓存
- ✓ 处理大型文档集
- ✓ 批量处理文档
- ✓ 监控延迟
- ✓ 实现分页
用户体验
- ✓ 清晰的回复格式
- ✓ 支持引用来源
- ✓ 文档浏览器/探索器
- ✓ 搜索建议
- ✓ 查询历史
- ✓ 导出对话
常见挑战与解决方案
挑战:回答无关
解决方案:
- 改进检索(提供更多上下文,使用更好的嵌入)
- 根据上下文验证答案
- 提出澄清问题
- 实施置信度评分
- 使用混合搜索
挑战:多轮对话中丢失上下文
解决方案:
- 保留对话记忆
- 根据历史记录更新检索
- 总结较长的对话
- 重新调整先前查询的权重
挑战:处理长文档
解决方案:
- 分层分块
- 先进行总结
- 优化问题
- 多跳检索
- 文档导航
挑战:上下文窗口有限
解决方案:
- 压缩检索到的上下文
- 使用文档摘要
- 分层检索
- 聚焦最相关的章节
- 迭代优化
高级功能
多文档分析
def compare_documents(question: str, documents: List[str]):
"""Analyze and compare across multiple documents"""
results = []
for doc in documents:
response = query_document(doc, question)
results.append({
"document": doc.name,
"answer": response
})
# Compare and synthesize
comparison = llm.generate(
f"Compare these answers: {results}"
)
return comparison
交互式文档探索
class DocumentExplorer:
def __init__(self, documents):
self.documents = documents
def browse_by_topic(self, topic):
"""Find documents by topic"""
pass
def get_related_documents(self, doc_id):
"""Find similar documents"""
pass
def get_key_terms(self, document):
"""Extract key terms and concepts"""
pass
资源
文档处理库
- PyPDF:处理 PDF
- python-docx:处理 Word 文档
- BeautifulSoup:网页抓取
- youtube-transcript-api:YouTube 字幕文本
聊天框架
- LangChain:综合框架
- LlamaIndex:专注于文档
- RAG 库:集成向量数据库
实施清单
- 选择要支持的文档来源
- 实现文档加载和处理
- 设置向量数据库/嵌入
- 构建聊天界面
- 实现对话管理
- 添加来源引用
- 处理边缘情况(大型文档、OCR 等)
- 实现错误处理
- 添加性能监控
- 使用真实文档进行测试
- 部署并监控
开始使用
- 从简单开始:单个 PDF,基础聊天
- 添加功能:多文档、对话历史
- 提升质量:更好的分块和检索
- 扩展规模:支持更多格式和更大的文档
- 完善体验:改进用户体验,处理错误
评论
支持 Markdown