BidiRag 是 BidiRAG 项目的高级封装类,提供统一的接口来:
from bdirag.bidi_rag import BidiRag
# 1. 初始化 BidiRag(推荐用于招投标公告)
rag = BidiRag(rag_method='bm25_html_tree')
# 2. 添加文档
rag.add_documents(["path/to/announcement1.html", "path/to/announcement2.html"])
# 3. 检索文档
results = rag.retrieve(
query="招标人和中标人",
top_k=5,
keywords=["招标人", "中标人", "采购人"]
)
# 4. 查看结果
for doc, score in results:
print(f"Score: {score:.3f}")
print(doc.page_content)
print("-" * 80)
# 搜索包含特定关键词的文档
results = rag.search_keywords(["招标人"], top_k=10)
# 搜索同时包含多个关键词的文档(AND 逻辑)
results = rag.search_keywords(["招标人", "中标人"], top_k=10)
# BM25 方法(关键词检索,无需 embedding 模型)
rag = BidiRag(rag_method='bm25')
# TF-IDF 方法
rag = BidiRag(rag_method='tfidf')
# HTML 结构感知方法(推荐用于招投标公告)
rag = BidiRag(rag_method='bm25_html_tree')
# 语义检索方法(需要 embedding 模型)
rag = BidiRag(rag_method='naive')
# 混合搜索方法
rag = BidiRag(rag_method='hybrid_search')
from openai import OpenAI
# 配置 LLM 客户端
llm_client = OpenAI(
api_key="your-api-key",
base_url="https://api.openai.com/v1"
)
# 使用支持 LLM 的 RAG 方法
rag = BidiRag(
rag_method='naive',
llm_client=llm_client,
llm_model='gpt-4o'
)
rag.add_texts([
"招标公告:招标人XX局,项目预算100万",
"中标公告:中标人XX公司,金额98万"
])
# 完整问答
result = rag.query(
query="谁是招标人?",
keywords=["招标人", "采购人"]
)
print("答案:", result.answer)
print("检索到的文档数:", len(result.retrieved_docs))
BidiRag(
rag_method: str = 'bm25_html_tree', # RAG 方法名称
chunk_size: int = 512, # 文档块大小
chunk_overlap: int = 50, # 块重叠大小
vector_store_type: str = 'faiss', # 向量存储类型
embedding_model_name: str = None, # Embedding 模型名称
llm_client=None, # LLM 客户端
llm_model: str = "gpt-4o", # LLM 模型名称
index_name: str = "default" # 索引名称
)
add_documents(sources, rebuild_index=True)添加文档文件(支持 HTML、PDF、DOCX、TXT 等)
sources: 文件路径或目录路径(字符串或列表)rebuild_index: 是否重建索引返回: 添加的文档数量
rag.add_documents(["doc1.html", "doc2.html"])
rag.add_documents("path/to/documents/") # 目录
add_texts(texts, metadata=None, rebuild_index=True)添加文本文档
texts: 文本内容列表metadata: 元数据列表(可选)rebuild_index: 是否重建索引返回: 添加的文档数量
rag.add_texts([
"<html><body>招标公告...</body></html>",
"<html><body>中标公告...</body></html>"
])
retrieve(query, top_k=None, keywords=None, return_scores=True)检索相关文档
query: 搜索查询(自然语言或关键词)top_k: 返回结果数量keywords: 额外关键词过滤(可选)return_scores: 是否返回相似度分数返回: 文档列表(带分数)
results = rag.retrieve(
query="采购信息",
top_k=5,
keywords=["招标人", "采购人", "中标人"]
)
query(query, top_k=None, keywords=None)完整 RAG 流程:检索 + 生成答案(需要 LLM)
query: 搜索查询top_k: 检索文档数量keywords: 关键词过滤返回: RAGResult 对象(包含答案和检索文档)
result = rag.query(
query="项目预算是多少?",
keywords=["预算", "金额"]
)
print(result.answer)
search_keywords(keywords, top_k=None)基于关键词精确搜索
keywords: 关键词列表(AND 逻辑)top_k: 最大结果数量返回: 文档列表
results = rag.search_keywords(["招标人", "中标人"], top_k=10)
get_document_count()获取已加载的文档数量
list_available_methods()列出所有可用的 RAG 方法
get_method_info()获取当前 RAG 方法的信息
clear()清除所有文档和索引
| 方法名 | 描述 | 适用场景 |
|---|---|---|
bm25 |
BM25 关键词检索 | 快速关键词匹配 |
tfidf |
TF-IDF 检索 | 简单关键词匹配 |
keyword |
关键词检索(BM25/TF-IDF) | 基础关键词搜索 |
bm25_html_tree |
HTML 结构感知的 BM25 | 招投标公告(推荐) |
| 方法名 | 描述 | 特点 |
|---|---|---|
naive |
基础语义检索 | 简单向量相似度搜索 |
rerank |
重排序检索 | 检索后使用重排序模型优化 |
hybrid_search |
混合搜索 | 结合向量搜索和关键词搜索 |
multi_query |
多查询检索 | 生成多个查询进行检索 |
hyde |
假设文档嵌入 | 基于假设文档的检索 |
step_back |
后退一步检索 | 生成更一般的查询 |
parent_document |
父文档检索 | 检索小块,返回大块 |
contextual_compression |
上下文压缩 | 压缩检索到的上下文 |
| 方法名 | 描述 | 特点 |
|---|---|---|
adaptive |
自适应检索 | 根据查询难度自适应策略 |
self_rag |
自反思检索 | 检索后进行自我评估 |
corrective |
纠正性检索 | 检索后进行纠正 |
flare |
FLARE 方法 | 生成与检索交替 |
raptor |
RAPTOR 方法 | 递归树聚合 |
ensemble |
集成检索 | 多种方法集成 |
from bdirag.bidi_rag import BidiRag
# 使用 HTML 结构感知方法
rag = BidiRag(rag_method='bm25_html_tree')
# 添加公告
html_content = """
<html>
<body>
<h1>政府采购中标公告</h1>
<table>
<tr><td>采购人</td><td>XX市财政局</td></tr>
<tr><td>中标人</td><td>XX科技有限公司</td></tr>
<tr><td>中标金额</td><td>500万元</td></tr>
</table>
</body>
</html>
"""
rag.add_texts([html_content])
# 检索招标人信息
results = rag.retrieve(
query="采购人信息",
keywords=["采购人", "招标人"]
)
for doc, score in results:
print(f"\n找到采购人信息 (score: {score:.3f}):")
print(doc.page_content)
import os
from bdirag.bidi_rag import BidiRag
rag = BidiRag(rag_method='bm25_html_tree')
# 处理目录中的所有 HTML 文件
announcement_dir = "data/announcements/"
rag.add_documents(announcement_dir)
print(f"已加载 {rag.get_document_count()} 个公告")
# 搜索特定信息
results = rag.retrieve(
query="太阳能路灯采购",
top_k=10,
keywords=["路灯", "照明", "采购"]
)
print(f"\n找到 {len(results)} 个相关公告")
rag = BidiRag(rag_method='bm25')
# 添加文档
rag.add_texts([
"招标人A公司,预算100万",
"招标人B公司,中标人C公司,预算200万",
"采购人D单位,预算150万"
])
# 只搜索包含"招标人"的文档
results = rag.retrieve(
query="公司信息",
keywords=["招标人"]
)
# 只搜索同时包含"招标人"和"中标人"的文档
results = rag.retrieve(
query="公司信息",
keywords=["招标人", "中标人"]
)
A: 可能的原因:
add_documents() 或 build_index()A: 建议:
bm25_html_tree(保留 HTML 结构)bm25 或 tfidfnaive 或 hybrid_searchnaive + llm_client)A: 默认使用 BAAI/bge-large-zh-v1.5 模型:
# 使用默认模型
rag = BidiRag(rag_method='naive')
# 或使用其他模型
rag = BidiRag(
rag_method='naive',
embedding_model_name='BAAI/bge-base-zh-v1.5'
)
A: 示例使用 OpenAI API:
from openai import OpenAI
llm_client = OpenAI(
api_key="your-api-key",
base_url="https://api.openai.com/v1" # 或使用其他兼容 API
)
rag = BidiRag(
rag_method='naive',
llm_client=llm_client,
llm_model='gpt-4o'
)
运行测试:
python examples/test_bidi_rag.py
运行完整示例:
python examples/demo_bidi_rag.py
网络问题: 如果使用 embedding 模型,需要访问 HuggingFace。如遇网络问题,可以:
bm25, tfidf, keyword, bm25_html_tree)内存使用: 大量文档时注意内存使用,可以分批处理
关键词过滤: 使用 keywords 参数时,文档必须包含所有关键词(AND 逻辑)
HTML 处理: bm25_html_tree 方法会解析 HTML 结构,适合结构化文档
如有问题,请查看:
examples/ 目录examples/test_bidi_rag.pybdirag/rag_methods/ 目录