Python使用Ollama實現(xiàn)私有大模型知識庫
在不依賴 LangChain、LlamaIndex 等框架,以及各種知識問答軟件的情況下,盡量減少第三方庫的使用,僅通過 Ollama 和 NumPy 兩個外部庫來實現(xiàn) RAG(Retrieval-Augmented Generation)應(yīng)用。
一、安裝python
下載:https://python.org/downloads/
安裝:一路下一步即可,安裝完成后運(yùn)行以下代碼,即可查看對應(yīng)版本號
python --version
二、安裝PyCharm
(推薦,也可以用vscode或windows記事本等編輯軟件)
PyCharm的優(yōu)點(diǎn):
- 自動提示
- 創(chuàng)建項目時自動創(chuàng)建python虛擬環(huán)境
- 整合本地終端(且基于python對應(yīng)本項目的虛擬環(huán)境)
三、安裝ollama
下載:https://ollama.com/download
安裝:一路下一步。安裝完成后用以下命令檢驗
ollama --version
四、在ollama中安裝開源chat大模型
在ollama中安裝開源chat大模型:qwen2.5 或deepseek-r1
ollama官網(wǎng)models(https://ollama.com/search)頁面可以找到很多開源大模型,我們下載用的比較多的千問中文大模型(顯卡差的建議安裝ollama2.5:0.5b)
ollama run qwen2.5
五、在ollama中安裝開源embedding大模型
在ollama中安裝開源embedding大模型:milkey/m3e nomic-embed-text
embedding作用是將問題和知識庫文本轉(zhuǎn)換成向量,便于查詢。
原本打算使用nomic-embed-text模型,但是使用時效果不好,發(fā)現(xiàn)m3e的效果不錯,所以改用m3e
ollama run milkey/m3e
六、在項目python虛擬環(huán)境中安裝ollama
pip install ollama
七、安裝numpy
pip install numpy
八、編寫代碼
項目文件目錄結(jié)構(gòu)如下圖
1. kb.py
import numpy as np from ollama import embeddings class Kb: def __init__(self, filepath): # 讀取文件內(nèi)容 content = self.read_file(filepath) # print(content) # 讀取拆分好的數(shù)組 self.chunks = self.split_content(content) # print(chunks) # for chunk in chunks: # print(chunk) # print('=' * 10) # 轉(zhuǎn)換成向量 self.embeds = self.get_embeddings(self.chunks) # 讀取文件 def read_file(self, filepath): with open(filepath, 'r', encoding='utf-8') as f: content = f.read() return content # 拆分知識庫 @staticmethod def split_content(content): chunks = content.split('# ') # 過濾掉空塊 chunks = [chunk.strip() for chunk in chunks if chunk.strip()] return chunks # 字符串轉(zhuǎn)向量(embeddings) def get_embedding(self, chunk): # milkey/m3e 0.642084887746903 # bge-m3 0.6073383067378445 # nomic-embed-text 完全找不到 res = embeddings(model='milkey/m3e', prompt=chunk) # print(chunk) # print(res) # print(res['embedding']) return res['embedding'] def get_embeddings(self, chunks): embeds = [] for chunk in chunks: embed = self.get_embedding(chunk) embeds.append(embed) return np.array(embeds) # 查詢相似性向量 def search(self, text): print(text) max_similarity = 0 max_similarity_index = 0 ask_embed = self.get_embedding(text) for kb_embed_index, kb_embed in enumerate(self.embeds): similarity = self.similarity(kb_embed, ask_embed) # print(similarity) # print(self.chunks[kb_embed_index]) if similarity > max_similarity: max_similarity = similarity max_similarity_index = kb_embed_index print(max_similarity) print(self.chunks[max_similarity_index]) # print(self.embeds[max_similarity_index]) # 返回查到的相關(guān)文本 return self.chunks[max_similarity_index] # 相似度 @staticmethod def similarity(A, B): # 計算點(diǎn)積 dot_product = np.dot(A, B) # 計算范數(shù) norm_A = np.linalg.norm(A) norm_B = np.linalg.norm(B) # 計算余弦相似度 cosine_sim = dot_product / (norm_A * norm_B) return cosine_sim
2. rag.py
from kb import Kb from ollama import chat, Message class Rag: def __init__(self, model, kb_filepath): self.kb_filepath = kb_filepath self.kb = Kb(kb_filepath) self.model = model self.prompt_template = """ 基于:%s 回答:%s """ def chat(self, message): # 用戶消息檢索相關(guān)上下文 context = self.kb.search(message) # print(context) # prompt = self.prompt_template % (context, message) prompt = '請基于以下內(nèi)容回答問題:\n' + context response = chat(self.model, [Message(role='system', content=prompt), Message(role='user', content=message)]) return response['message']
3. index.py
from rag import Rag rag = Rag('deepseek-r1:14b', '私人知識庫.txt') msg = rag.chat('請介紹下劉芳') print(msg)
4. 私人知識庫.txt
MIS部門人員名單
# 1. 張小剛
姓名:張小剛
性別:男
愛好:打籃球、踢足球
電話:132233444
籍貫:山東菏澤# 2. 李光亮
姓名:李光亮
性別:男
愛好:踢足球、打排球
電話:15959595
籍貫:河南平頂山# 3. 王麗麗
姓名:王麗麗
性別:女
愛好:游泳、閱讀
電話:138123456
籍貫:江蘇南京# 4. 陳大明
姓名:陳大明
性別:男
愛好:跑步、爬山
電話:139876543
籍貫:浙江杭州# 5. 劉芳
姓名:劉芳
性別:女
愛好:瑜伽、繪畫
電話:137112233
籍貫:廣東深圳# 6. 趙強(qiáng)
姓名:趙強(qiáng)
性別:男
愛好:打羽毛球、釣魚
電話:135665544
籍貫:四川成都# 7. 孫婷婷
姓名:孫婷婷
性別:女
愛好:跳舞、唱歌
電話:136778899
籍貫:福建廈門# 8. 周偉
姓名:周偉
性別:男
愛好:打乒乓球、下棋
電話:134556677
籍貫:湖南長沙# 9. 吳曉梅
姓名:吳曉梅
性別:女
愛好:攝影、旅行
電話:133445566
籍貫:湖北武漢# 10. 鄭小龍
姓名:鄭小龍
性別:男
愛好:打籃球、游泳
電話:132334455
籍貫:陜西西安# 11. 高靜
姓名:高靜
性別:女
愛好:閱讀、寫作
電話:131223344
籍貫:遼寧沈陽# 12. 林浩
姓名:林浩
性別:男
愛好:踢足球、跑步
電話:130112233
籍貫:廣西南寧# 13. 黃雅婷
姓名:黃雅婷
性別:女
愛好:跳舞、瑜伽
電話:139001122
籍貫:云南昆明# 14. 徐志強(qiáng)
姓名:徐志強(qiáng)
性別:男
愛好:打排球、爬山
電話:138990011
籍貫:貴州貴陽# 15. 何麗
姓名:何麗
性別:女
愛好:繪畫、攝影
電話:137889900
籍貫:江西南昌# 16. 馬超
姓名:馬超
性別:男
愛好:打籃球、釣魚
電話:136778899
籍貫:山西太原# 17. 郭曉燕
姓名:郭曉燕
性別:女
愛好:唱歌、旅行
電話:135667788
籍貫:河北石家莊# 18. 羅志勇
姓名:羅志勇
性別:男
愛好:踢足球、下棋
電話:134556677
籍貫:吉林長春# 19. 鄧麗麗
姓名:鄧麗麗
性別:女
愛好:瑜伽、閱讀
電話:133445566
籍貫:黑龍江哈爾濱# 20. 許文強(qiáng)
姓名:許文強(qiáng)
性別:男
愛好:打羽毛球、跑步
電話:132334455
籍貫:安徽合肥# 21. 韓雪
姓名:韓雪
性別:女
愛好:跳舞、攝影
電話:131223344
籍貫:甘肅蘭州# 22. 曹陽
姓名:曹陽
性別:男
愛好:打籃球、爬山
電話:130112233
籍貫:青海西寧# 23. 謝婷婷
姓名:謝婷婷
性別:女
愛好:唱歌、繪畫
電話:139001122
籍貫:寧夏銀川# 24. 董志剛
姓名:董志剛
性別:男
愛好:踢足球、釣魚
電話:138990011
籍貫:新疆烏魯木齊# 25. 蘇靜
姓名:蘇靜
性別:女
愛好:閱讀、旅行
電話:137889900
籍貫:內(nèi)蒙古呼和浩特# 26. 潘偉
姓名:潘偉
性別:男
愛好:打乒乓球、下棋
電話:136778899
籍貫:海南???/p># 27. 鐘麗
姓名:鐘麗
性別:女
愛好:瑜伽、攝影
電話:135667788
籍貫:重慶# 28. 田小龍
姓名:田小龍
性別:男
愛好:打籃球、游泳
電話:134556677
籍貫:天津# 29. 白曉梅
姓名:白曉梅
性別:女
愛好:跳舞、唱歌
電話:133445566
籍貫:北京# 30. 石浩
姓名:石浩
性別:男
愛好:踢足球、跑步
電話:132334455
籍貫:上海
通過以上代碼,可基本實現(xiàn)用RAG技術(shù),搭建本地知識庫問答AI助理,非流式回復(fù)(steam=False)。需要等待大模型輸出所有文字之后,才能全部返回,太慢,肯定要實現(xiàn)一般聊天大模型的流式回復(fù)(steam=True)
首先,在rag.py中增加以下方法
def stream_chat(self, message): context = self.kb.search(message) prompt = '請基于以下內(nèi)容回答問題:\n' + context response = chat(self.model, [Message(role='system', content=prompt), Message(role='user', content=message)], stream=True) # 遍歷流式響應(yīng) for chunk in response: print(chunk['message']['content'], end='', flush=True) # 實時打印輸出 print() # 輸出完成后換行
然后,調(diào)整index.py代碼為
from rag import Rag rag = Rag('deepseek-r1:14b', '私人知識庫.txt') rag.stream_chat('請介紹下劉芳')
經(jīng)過以上的修改,就可以看到AI的流式答復(fù)了。
注:以上RAG只是獲取到了本地知識庫中的最為匹配的一條記錄,如果需要實現(xiàn)一次性獲取多個關(guān)聯(lián)內(nèi)容,并根據(jù)多個關(guān)聯(lián)內(nèi)容進(jìn)行答復(fù),需要使用向量數(shù)據(jù)庫。
以上就是Python使用Ollama實現(xiàn)私有大模型知識庫的詳細(xì)內(nèi)容,更多關(guān)于Python Ollama實現(xiàn)知識庫的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python實現(xiàn)實時數(shù)據(jù)采集新型冠狀病毒數(shù)據(jù)實例
在本篇文章里小編給大家整理了關(guān)于Python實現(xiàn)實時數(shù)據(jù)采集新型冠狀病毒數(shù)據(jù)實例內(nèi)容,有需要的朋友們可以學(xué)習(xí)參考下。2020-02-02python pandas合并Sheet,處理列亂序和出現(xiàn)Unnamed列的解決
這篇文章主要介紹了python pandas合并Sheet,處理列亂序和出現(xiàn)Unnamed列的解決方案,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-03-03Pytorch中TensorBoard及torchsummary的使用詳解
這篇文章主要介紹了Pytorch中TensorBoard及torchsummary的使用詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-05-05Python 調(diào)用有道翻譯接口實現(xiàn)翻譯
這篇文章主要介紹了Python 調(diào)用有道翻譯接口實現(xiàn)翻譯,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03Python中標(biāo)準(zhǔn)模塊importlib詳解
這篇文章主要給大家詳細(xì)介紹了Python中標(biāo)準(zhǔn)模塊importlib的使用方法和示例,非常簡單,有需要的小伙伴可以參考下2017-04-04