一,下载 Milvus 和 Ollama

请看别的专门的教程

windows 环境下安装 Milvus_windows安装milvus-CSDN博客

二,Milvus 建表

Attu 能提供图形化界面操作,但实际使用时有 bug,比如我不能创建 varchar 字段,这里演示用python 建表和插入,Attu 的其他操作还行能用。

建表:

from pymilvus import connections, Collection, utility
from langchain_ollama import OllamaEmbeddings, OllamaLLM
from langchain_milvus.vectorstores import Milvus
from langchain.chains import RetrievalQA

def create_collection(database_name: str, collection_name: str):
    connections.connect(host='localhost', port='19530', db_name=database_name)
    if utility.has_collection(collection_name):
        print(f"集合 {collection_name} 已存在,终止")
        return
    fields = [
        FieldSchema(name="id", dtype=DataType.VARCHAR, is_primary=True, max_length=256, description="主键"),
        FieldSchema(name="vectors", dtype=DataType.FLOAT_VECTOR, dim=768, description="向量"),
        FieldSchema(name="text", dtype=DataType.VARCHAR, max_length=256, description="内容"),
    ]
    schema = CollectionSchema(fields, description="schema")
    collection = Collection(name=collection_name, schema=schema)

    # 创建索引
    if not collection.has_index():
        index_params = {
            "index_type": "HNSW",
            "metric_type": "L2",
            "params": {
                "M": 16,
                "efConstruction": 512
            }
        }
        collection.create_index(
            field_name="vectors",
            index_params=index_params
        )

collection 就相当于表,一定记得创建索引,否则无法搜索。

三,准备 Ollama 模型

需要准备一个 embedding 模型,用来把文字转化为向量。

还需要一个 llm 模型,用来对话。

下载方法请搜索 Ollama 的教程。

四,插入

用 Ollama 的向量模型计算向量:

from langchain_ollama import OllamaEmbeddings

EMBED_MODEL_NAME = "nomic-embed-text:v1.5"

class Embed:
    def __init__(self):
        self.embedding = OllamaEmbeddings(model=EMBED_MODEL_NAME)

    def get_vectors(self, prompts: list[str]) -> list[list[float]]:
        # 维度 768
        return self.embedding.embed_documents(prompts)

得到向量后将向量数组填入vectors,id就填入id,反正字段根据自己需求自己设计,最后都放入一个 dict,就是下面的 dataa, 可以批量导入,格式是
 

{
    id: [data_1_id, data_2_id, ...],
    vectors: [[data_1_vector1, data_1_vector2, ...],[data_2_vector1, data_2_vector2, ...], ...],
    text: [data_1_text, data_2_text, ...]
}

插入:

    def insert(collection_name, dataa):
        connections.connect(host='localhost', port='19530')
        collection = Collection(collection_name)
        collection.insert(dataa)
        collection.load()

五,构建RAG链

from pymilvus import connections, Collection, utility
from langchain_ollama import OllamaEmbeddings, OllamaLLM
from langchain_milvus.vectorstores import Milvus
from langchain.chains import RetrievalQA

def call(question: str):
    qa_chain = __get_qa_chain("default", "my_collection")
    response = qa_chain.invoke({"query": question})

    return f"{response["result"]}\n资料饮用为:\n{response["source_documents"][0].page_content}\n"

def __get_qa_chain(database_name: str, collection_name: str):
    # 你的 milvus 服务器
    host = "localhost"
    port = 19530
    connections.connect(
        alias=database_name,
        host=host,
        port=port
    )

    if not utility.has_collection(collection_name):
        raise ValueError(f"Collection '{collection_name}' does not exist")
    
    # 得到 collection 对象
    milvus_collection = Collection(collection_name)
    milvus_collection.load()
    
    # 你的 Ollama 向量模型
    embeddings = OllamaEmbeddings(model=YOUR_EMBED_MODEL_NAME)

    # 封装 Milvus 检索器
    vector_db = Milvus(
        embedding_function=embeddings,
        collection_name=collection_name,
        connection_args={"host": host, "port": port},
        consistency_level="Strong",
        vector_field="vectors",
        enable_dynamic_field=True,
        text_field="text"
    )

    # 你的 Ollama 大语言模型
    llm = OllamaLLM(model=YOUR_OLLAMA_LLM_MODEL_NAME)

    # 构建 RAG 链
    qa_chain = RetrievalQA.from_chain_type(
        llm=llm,
        retriever=vector_db.as_retriever(
            search_kwargs={
                "k": 3,
                "param": {
                    "metric_type": "L2"
                }
            }
        ),
        chain_type="stuff",
        return_source_documents=True
    )

    return qa_chain

六,注意

如果出现莫名奇妙的报错,把这些东西都试着更新到最新版试试。

如果出现报错:向量字段无法作为输出属性,请更新 milvus 版本

如果想控制输出字段 `output_fields`,不要听信Ai:

            search_kwargs={
                "k": 3,
                "param": {
                    "metric_type": "L2"
                    "output_fields": ["1", "2", ...] # 错的,用不了
                }
            }

会因为重复设置 output_fields 而报错,源码里面已经硬编码了一次设置 output_fields ,不知道 Ai 哪编出来能这样设置的。

如果真想,这两个神秘属性可以控制输出哪个字段(在封装 Milvus 检索器那部分)

enable_dynamic_field=True,
text_field="text"

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐