基于Ollama模型,通过RAG实现问答式定制化回复

RAG与Ollama实现问答定制化回复

      RAG:检索增强生成(Retrieval-Augmented Generation),是一种通过将人工智能(AI)模型与外部知识库连接来优化其性能的架构。RAG可帮助大语言模型(LLM)以更高质量提供更相关的响应

      RAG允许生成式AI模型(generative AI model)访问其他外部知识库,例如内部组织数据、学术期刊和专业数据集。通过将相关信息集成到生成过程中,聊天机器人(chatbots)和其他自然语言处理(NLP)工具无需进一步训练即可创建更准确的特定领域内容。

      生成式AI模型具有知识截止点,即其训练数据上次更新的时间点。随着模型的老化,其相关性会逐渐降低。RAG系统实时连接模型与补充外部数据,并将最新信息整合到生成的响应中。

      RAG模型还可以通过应用程序编程接口(API)连接到互联网,并访问实时社交媒体信息和消费者评论,从而更好地了解市场情绪。同时,由于模型将检索到的信息整合到文本生成过程中,访问突发新闻和搜索引擎可以带来更准确的响应。

      诸如OpenAI的GPT之类的生成式AI模型通过检测数据中的模式来工作,然后利用这些模式预测用户输入的最可能结果。有时,模型会检测到不存在的模式。当模型将不正确或虚构的信息呈现为事实时,就会出现幻觉或虚构

      RAG通过将信息检索模型(information retrieval model)与生成式AI模型相结合来生成更权威的内容。RAG系统会查询知识库,并在生成响应之前为用户提示词添加更多上下文

      RAG包含两个阶段:检索和内容生成。在检索阶段,算法搜索并检索与用户提示或问题相关的信息片段。这些外部知识会被附加到用户的提示中,并传递给语言模型。在生成阶段,LLM会从增强的提示词及其训练数据的内部表示中提取信息,以合成一个针对用户当时情况的答案。

      构建RAG管道(pipeline)的第一步是将数据导入向量数据库(vector database)。

      这里问答式数据来自于本人的csdn博客,question为博客标题,answer为对应标题的链接,csdn.jsonl内容示例如下:

{"question": "C++20中线程类std::jthread的使用", "answer": "https://blog.youkuaiyun.com/fengbingchun/article/details/152172174"}
{"question": "通过提示词工程(Prompt Engineering)方法重新生成从Ollama下载的模型", "answer": "https://blog.youkuaiyun.com/fengbingchun/article/details/151902070"}
{"question": "使用C++实现与Ollama通信:ollama-hpp", "answer": "https://blog.youkuaiyun.com/fengbingchun/article/details/151677357"}
{"question": "Ollama Python库的使用", "answer": "https://blog.youkuaiyun.com/fengbingchun/article/details/151286661"}
{"question": "解析、创建Excel文件的开源库OpenXLSX介绍", "answer": "https://blog.youkuaiyun.com/fengbingchun/article/details/151259362"}
{"question": "Qt中的QSS介绍", "answer": "https://blog.youkuaiyun.com/fengbingchun/article/details/151020879"}
{"question": "深度学习中的模型量化及实现示例", "answer": "https://blog.youkuaiyun.com/fengbingchun/article/details/150703580"}
{"question": "图像相似度算法汇总及Python实现", "answer": "https://blog.youkuaiyun.com/fengbingchun/article/details/150451109"}
{"question": "深度学习中的模型知识蒸馏", "answer": "https://blog.youkuaiyun.com/fengbingchun/article/details/149878692"}
{"question": "深度学习中基于响应的模型知识蒸馏实现示例", "answer": "https://blog.youkuaiyun.com/fengbingchun/article/details/150112972"}

      下面是实现示例代码,依赖ollama python库,向量数据库使用chroma,不依赖sentence-transformers和langchain,当用户输入问题时,首先检索数据库,若命中则直接返回对应的链接;若未命中,则调用Ollama的模型进行推理

def parse_args():
	parser = argparse.ArgumentParser(description="ollama rag chat")
	parser.add_argument("--llm_model", type=str, default="qwen3:1.7b", help="llm model name, for example:qwen3:1.7b")
	parser.add_argument("--embed_model", type=str, default="nomic-embed-text:v1.5", help="embedded model, for example:nomic-embed-text:v1.5")
	parser.add_argument("--jsonl", type=str, default="csdn.jsonl", help="jsonl(JSON Lines) file")
	parser.add_argument("--db_dir", type=str, default="chroma_db_ollama", help="vector database(chromadb) storage path, for example:chroma_db_ollama")
	parser.add_argument("--similarity_threshold", type=float, default=0.8, help="similarity threshold, the higher the stricter")
	parser.add_argument("--question", type=str, help="question")

	args = parser.parse_args()
	return args

def build_vector_db(db_dir, jsonl, embed_model):
	client = chromadb.PersistentClient(path=db_dir)
	collection = client.get_or_create_collection("csdn_qa_ollama")
	if collection.count() > 0:
		return collection

	print("start building vector database ...")

	with open(jsonl, "r", encoding="utf-8") as f:
		data = [json.loads(line.strip()) for line in f]

	for i, item in enumerate(tqdm(data, desc="Embedding with Ollama")):
		question = item["question"]
		answer = item["answer"]

		res = ollama.embeddings(model=embed_model, prompt=question)
		emb = res["embedding"]

		collection.add(
			ids=[str(i)],
			embeddings=[emb],
			metadatas=[{"question": question, "answer": answer}]
		)
		time.sleep(0.05)

	print(f"vector database is built and a total of {len(data)} entries are imported")
	return collection

def retrieve_answer(embed_model, collection, similarity_threshold, question):
	res = ollama.embeddings(model=embed_model, prompt=question)
	query_vec = res["embedding"]
	results = collection.query(query_embeddings=[query_vec], n_results=1)
	if not results["ids"]:
		return None

	meta = results["metadatas"][0][0]
	score = 1 - results["distances"][0][0]
	if score >= similarity_threshold:
		return f"question: {meta['question']}; link: {meta['answer']}"
	return None

def chat(llm_model, embed_model, jsonl, db_dir, similarity_threshold, question):
	collection = build_vector_db(db_dir, jsonl, embed_model)
	ans = retrieve_answer(embed_model, collection, similarity_threshold, question)
	if ans:
		print(ans)
	else:
		try:
			stream = ollama.chat(model=llm_model, messages=[{"role": "user", "content": question}], stream=True)
			print("Answer: ", end="", flush=True)

			for chunk in stream:
				if 'message' in chunk and 'content' in chunk['message']:
					content = chunk['message']['content']
					print(content, end="", flush=True)
			print() # line break
		except Exception as e:
			print(f"Error: {e}")

if __name__ == "__main__":
	colorama.init(autoreset=True)
	args = parse_args()

	chat(args.llm_model, args.embed_model, args.jsonl, args.db_dir, args.similarity_threshold, args.question)

	print(colorama.Fore.GREEN + "====== execution completed ======")

      当命中时输出结果如下:

      当未命中时输出结果如下:

      GitHubhttps://github.com/fengbingchun/NN_Test

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值