🎯 编者常常有许多材料需要阅读查阅,但自己又比较懒,为此,想在大模型的学习过程中基于RAG技术将本地知识库与大模型结合起来,加快自身的效率。
在本次的项目设计,需要达成以下目标:
🟢 开源大模型的本地部署及使用 (以Deepseek为例);
🟢 PDF文本分析 ➕ 相似prompt检索提取 (关键);
🟢 将检索到的信息与原prompt结合作为输入,得到结果;
def extract_text_from_pdf(pdf_path):
text = ""
with pdfplumber.open(pdf_path) as pdf:
for page in pdf.pages:
text += page.extract_text()
return text
def split_into_paragraphs(text, min_length=3):
paragraphs = [p.strip() for p in text.split('\n') if len(p.strip()) >= min_length]
return paragraphs
# 示例:提取PDF文本并分块
pdf_text = extract_text_from_pdf("mypdf.pdf")
paragraphs = split_into_paragraphs(pdf_text)
from sentence_transformers import SentenceTransformer
import faiss
# 编码结果
model = SentenceTransformer("all-MiniLM-L6-v2")
doc_embeddings = model.encode(paragraphs)
# 构建FAISS索引
dimension = doc_embeddings.shape[1]
index = faiss.IndexFlatL2(dimension)
index.add(doc_embeddings)
def retrieve_docs(query, k=3):
"""检索最相关的k个段落"""
query_vec = model.encode([query])
D, I = index.search(query_vec, k=k) # D是距离,I是索引
return [paragraphs[i] for i in I[0]]
query = "境外生获得省部级及以上学科竞赛奖项奖励金额可以提高多少?"
retrieved = retrieve_docs(query, k=3)
print("\n检索到的相关段落:")
for i, doc in enumerate(retrieved):
print(f"[{i+1}] {doc[:100]}...") # 打印前100字符
问题:境外生获得省部级及以上学科竞赛奖项奖励金额可以提高多少?
检索Top3结果: 参考1 - 8 -(境外生排位第一)获得省部级及以上学科竞赛奖项,奖励金额 参考2 1.学校对获得省部级及以上学科竞赛奖项的学生给予奖励, 参考3 培训费以及学生奖金等。
🔴 可以发现,这个相似的检索结果中并没有显示我们想要的答案,我们进一步分析生成的paragraphs
, 如下所示,可以发现基于pdfplumber
库生成的段落都是断断续续的,并不能自成一段。因为pdfplumber
库是按行提取的,缺乏对上下文的理解,换行默认为新的一段。
'- 8 -(境外生排位第一)获得省部级及以上学科竞赛奖项,奖励金额', '可提高 10%。',
🟢 为此还需要对分段的语句进行处理:
def smart_merge_lines(lines, min_len=30, join_limit=200):
paragraphs = []
buffer = ""
for line in lines:
line = line.strip()
if not line:
continue
buffer += " " + line
if len(buffer) >= min_len and re.search(r"[。!?;:]$", buffer.strip()):
paragraphs.append(buffer.strip())
buffer = ""
elif len(buffer) >= join_limit:
paragraphs.append(buffer.strip())
buffer = ""
if buffer:
paragraphs.append(buffer.strip())
return paragraphs
def extract_paragraphs_from_pdf(pdf_path):
raw_lines = []
with pdfplumber.open(pdf_path) as pdf:
for page in pdf.pages:
text = page.extract_text()
if text:
raw_lines.extend(text.split('\n'))
merged_paragraphs = smart_merge_lines(raw_lines)
return merged_paragraphs
paragraphs = extract_paragraphs_from_pdf("mypdf.pdf")
print(paragraphs)
请根据以下参考内容回答问题: 参考1 4.鼓励境外生积极参与学科竞赛活动,境外生个人或团体 - 8 - (境外生排位第一)获得省部级及以上学科竞赛奖项,奖励金额 可提高 10%。 参考2 第三章 赛事分类与级别认定 第七条 根据学科竞赛的组织机构、专业度、社会影响和获 - 4 - 奖难度等方面综合考虑,将竞赛分为国家级、省部级、地厅级和 校级赛事。省部级及以上学科竞赛项目原则上需具有下一级别的 竞争性选拔过程。 参考3 4.奖金发放:学校归口管理职能部门根据最终确定的奖励情 况,按要求报送相关奖励方案,由财务处发放奖金。
messages = [
{"role": "user", "content": f"""请根据以下参考内容回答问题:
{retrieved}
问题:{query}"""}
]
mode_name_or_path = '/root/autodl-tmp/deepseek-ai/deepseek-llm-7b-chat'
# 加载预训练的分词器和模型
tokenizer = AutoTokenizer.from_pretrained(mode_name_or_path, trust_remote_code=True)
llm = AutoModelForCausalLM.from_pretrained(mode_name_or_path, trust_remote_code=True, torch_dtype=torch.bfloat16,
device_map="auto")
llm.generation_config = GenerationConfig.from_pretrained(mode_name_or_path)
llm.generation_config.pad_token_id = llm.generation_config.eos_token_id
llm.eval() # 设置模型为评估模式
input_tensor = tokenizer.apply_chat_template(
messages,
add_generation_prompt=True, # 添加"Assistant:"提示
return_tensors="pt"
)
outputs = llm.generate(input_tensor.to(llm.device), max_new_tokens=200)
result = tokenizer.decode(outputs[0][input_tensor.shape[1]:], skip_special_tokens=True)
print("\n最终回答:", result)
最终回答: 根据提供的内容,境外生个人或团体获得省部级及以上学科竞赛奖项,奖励金额可以提高10%。
✅ 本项目搭建了一个简单的知识库问答系统,用户可以将自己的私人知识库进行搭建,基于RAG技术实现问答系统;
❌ 在项目深度还缺少更细节的处理,例如在检索方面,还可以采用实现混合检索策略:BM25 + 稠密向量检索(如BGE嵌入);加入重排序机制:使用Cross-Encoder对初筛结果进行相关性重排
✅ 若有该项目的代码需求,可以三连获取 ❗❗❗
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。