使用 LlamaIndex 做一个智能体根据 PDF 回答问题

什么是LlamaIndex

LlamaIndex 是一个为开发「上下文增强」的大语言模型应用的框架(也就是SDK)。上下文增强,泛指任何在私有或特定领域数据基础上应用大语言模型的情况。例如:

  • Question-Answering Chatbots (也就是 RAG)

  • Document Understanding and Extraction (文档理解与信息抽取)

  • Autonomous Agents that can perform research and take actions (智能体应用)

LlamaIndex 有 Python 和 Typescript 两个版本,Python 版的文档相对更完善。

安装

pip install llama-index

加载数据

通过 SimpleDirectoryReader 可以将本地的数据库加载,后期供大模型使用

支持的文件类型:

  • .csv - comma-separated values
  • .docx - Microsoft Word
  • .epub - EPUB ebook format
  • .hwp - Hangul Word Processor
  • .ipynb - Jupyter Notebook
  • .jpeg.jpg - JPEG image
  • .mbox - MBOX email archive
  • .md - Markdown
  • .mp3.mp4 - audio and video
  • .pdf - Portable Document Format
  • .png - Portable Network Graphics
  • .ppt.pptm.pptx - Microsoft PowerPoint

举个例子

from llama_index.core import SimpleDirectoryReader

reader = SimpleDirectoryReader(
        input_dir="./data", # 目标目录
        recursive=False, # 是否递归遍历子目录
        required_exts=[".pdf"] # (可选)只读取指定后缀的文件
    )
documents = reader.load_data()

为了方便展示,我们定义一个函数来展示对象的内部结构

import json
from pydantic.v1 import BaseModel

def show_json(data):
    """用于展示json数据"""
    if isinstance(data, str):
        obj = json.loads(data)
        print(json.dumps(obj, indent=4))
    elif isinstance(data, dict) or isinstance(data, list):
        print(json.dumps(data, indent=4))
    elif issubclass(type(data), BaseModel):
        print(json.dumps(data.dict(), indent=4, ensure_ascii=False))

我从网上下载了一些研报 pdf 做测试,现在打印一下 documents 是什么

show_json(documents[0])

输出:

{
    "id_": "8e087dc2-45c9-4d2b-a743-e0a20493fa2f",
    "embedding": null,
    "metadata": {
        "file_path": "D:\\Code\\Python\\Hello\\AI\\01\\data\\docstore.json",
        "file_name": "docstore.json",
        "file_type": "application/json",
        "file_size": 2,
        "creation_date": "2024-06-26",
        "last_modified_date": "2024-06-26"
    },
    "excluded_embed_metadata_keys": [
        "file_name",
        "file_type",
        "file_size",
        "creation_date",
        "last_modified_date",
        "last_accessed_date"
    ],
    "excluded_llm_metadata_keys": [
        "file_name",
        "file_type",
        "file_size",
        "creation_date",
        "last_modified_date",
        "last_accessed_date"
    ],
    "relationships": {},
    "text": "{}",
    "mimetype": "text/plain",
    "start_char_idx": null,
    "end_char_idx": null,
    "text_template": "{metadata_str}\n\n{content}",
    "metadata_template": "{key}: {value}",
    "metadata_seperator": "\n",
    "class_name": "Document"
}

正好是一个 text 为空的一段,这段对于大模型来说是没有有效信息的

正常的应该是这样

{
    "id_": "c392bb17-90ce-4c5f-89b6-abb2ae7c890a",
    "embedding": null,
    "metadata": {
        "page_label": "7",
        "file_name": "spyl.pdf",
        "file_path": "D:\\Code\\Python\\Hello\\AI\\01\\data\\spyl.pdf",
        "file_type": "application/pdf",
        "file_size": 743694,
        "creation_date": "2024-06-25",
        "last_modified_date": "2024-06-25"
    },
    "excluded_embed_metadata_keys": [
        "file_name",
        "file_type",
        "file_size",
        "creation_date",
        "last_modified_date",
        "last_accessed_date"
    ],
    "excluded_llm_metadata_keys": [
        "file_name",
        "file_type",
        "file_size",
        "creation_date",
        "last_modified_date",
        "last_accessed_date"
    ],
    "relationships": {},
    "text": " 行业简评报告 证券研究报告  \n \n \n请务必仔细阅读本报告最后部分的重要法律说明  \n5 据会稽山绍兴酒,今年 618,会稽山新品气泡黄酒 “一日一熏 ”在其抖音官方直播间  \n72小时卖出 1000万+,是抖音黄酒类第 2~10名总和的 100倍,且成交 80%以上都是年\n轻人。此外,根据数据统计, 6月12日-6月15日,气泡黄酒在抖音端销售额超过了啤\n酒热卖的前三销售额的总和,抢占部分啤酒市场。  \n资料来源: 酒业家  \n \n【5月规上白酒产量同比增长 4.9%】  \n国家统计局数据显示, 5月,中国规模以上企业白酒(折 65度,商品量)产量 36.1\n万千升,同比增长 4.9%;啤酒产量 353.5万千升,同比下降 4.5%;葡萄酒产量 0.8万千\n升, 同比下降 11.1%。1-5月, 中国规模以上企业累计白酒 (折 65度, 商品量) 产量 190.2\n万千升,同比增长 6.5%;啤酒产量 1504.5万千升,同比增长 0.7%;葡萄酒产量 4.9万\n千升,与上年同期持平。  \n资料来源: 酒业家  \n \n【伊利开卖无酒精饮料畅意 100%奶啤】  \n日前,伊利推出一款“酒精健康替代”新品 ——畅意 100%奶啤,产品定位为一款\n有情绪价值的无酒精饮料,适合消费者在商务宴请、好友聚餐、 KTV等场景下饮用,喝\n完还能开车。在酸甜好喝的同时更低负担,产品还添加有伊利自有菌株 K56,改善肠道\n环境,助力畅快嗨吃无负担。目前,畅意 100%奶啤将重点聚焦餐饮场景解辣解腻,还\n可以辐射到追剧、打游戏、下午茶等场景。 6月1日量产, 6月底铺货,将先在西南地\n区线下渠道发售,覆盖传统渠道、餐饮、便利店、校园场景等,定价 5元/瓶( 300mL)。 \n资料来源: 食品板  \n \n4风险提示  \n宏观经济不及预期,行业竞争加剧,食品安全风险。",
    "mimetype": "text/plain",
    "start_char_idx": null,
    "end_char_idx": null,
    "text_template": "{metadata_str}\n\n{content}",
    "metadata_template": "{key}: {value}",
    "metadata_seperator": "\n",
    "class_name": "Document"
}

Process finished with exit code 0

我们可以对 SimpleDirectoryReader 读取到的数据进行进一步的处理

def gen_nodes():
    docs = SimpleDirectoryReader("./data", required_exts=[".pdf"], file_extractor={".pdf": PyMuPDFReader()}).load_data()
    node_parser = TokenTextSplitter(
        separator="\n\n",
        backup_separators=["\n", " 。", "!", "?", ";", "?", "!"],
        chunk_size=500,
        chunk_overlap=100
    )
    nodes = node_parser.get_nodes_from_documents(docs)
    return nodes

nodes = gen_nodes()

show_json(nodes[0])

在上面代码中我们通过 TokenTextSplitter 对文本进行切分,切分后每一个 chunk 的大小是 500 token, 上下chunk 可重复的部分不超过 100 token, 这样处理后,空的无效信息就会被过滤掉,长度不够的会合并一起,同时因为有交叠信息,避免搜索的时候漏掉一些关键信息。

输出:

{
    "id_": "6c5b4339-fdc6-447e-b46b-611c6ccd1859",
    "embedding": null,
    "metadata": {
        "file_path": "D:\\Code\\Python\\Hello\\AI\\01\\data\\spyl.pdf",
        "file_name": "spyl.pdf",
        "file_type": "application/pdf",
        "file_size": 743694,
        "creation_date": "2024-06-25",
        "last_modified_date": "2024-06-25",
        "total_pages": 8,
        "source": "1"
    },
    "excluded_embed_metadata_keys": [
        "file_name",
        "file_type",
        "file_size",
        "creation_date",
        "last_modified_date",
        "last_accessed_date"
    ],
    "excluded_llm_metadata_keys": [
        "file_name",
        "file_type",
        "file_size",
        "creation_date",
        "last_modified_date",
        "last_accessed_date"
    ],
    "relationships": {
        "1": {
            "node_id": "559905da-f246-4f84-bcde-5288d5059a13",
            "node_type": "4",
            "metadata": {
                "file_path": "D:\\Code\\Python\\Hello\\AI\\01\\data\\spyl.pdf",
                "file_name": "spyl.pdf",
                "file_type": "application/pdf",
                "file_size": 743694,
                "creation_date": "2024-06-25",
                "last_modified_date": "2024-06-25",
                "total_pages": 8,
                "source": "1"
            },
            "hash": "f22de76d5bdd9b79b9d34e322259bc405ca22b4f5f145934b6331206705c027f",
            "class_name": "RelatedNodeInfo"
        },
        "3": {
            "node_id": "ea84330b-a299-43c3-966b-c3224e2c4137",
            "node_type": "1",
            "metadata": {},
            "hash": "3028fef80d36c6d11e4a376eb0e09ca8afee25b24ac021f3bf246beb1d3b3b8c",
            "class_name": "RelatedNodeInfo"
        }
    },
    "text": "1 \n \n[Table_Rank] \n评级: 看好 \n \n[Table_Authors] \n \n赵瑞 \n分析师 \nSAC 执证编号:S0110522120001 \nzhaorui@sczq.com.cn \n \n \n \n[Table_Chart] \n市场指数走势(最近1 年) \n \n \n资料来源:聚源数据 \n相关研究 \n[Table_OtherReport] \n \n底部寻金,四维聚焦优选稳健和关注\n困境反转两类标的—— 2024 白酒行\n业年度策略报告 \n \n激荡三十年,白酒龙头企业兴衰沉浮的\n启示与展望 \n \n关注食品消费新品类,猪价保持弱势\n震荡 \n \n \n \n核心观点 \n[Table_Summary] \n \n⚫ \n酒水市场:据今日酒价数据,截至6 月23 日,24 年飞天原箱、散\n瓶批价分别为2420 元、2140 元,周环比分别下降180 元、150 元,\n飞天批价自6 月14 日阶段性低点企稳回升之后,再次出现快速下\n探。近期飞天批价波动主要由于在宏观经济仍处弱复苏、以及酒水",
    "mimetype": "text/plain",
    "start_char_idx": 2,
    "end_char_idx": 453,
    "text_template": "{metadata_str}\n\n{content}",
    "metadata_template": "{key}: {value}",
    "metadata_seperator": "\n",
    "class_name": "TextNode"
}

其他的 TextSplitter

  • SentenceSplitter:在切分指定长度的 chunk 同时尽量保证句子边界不被切断;
  • CodeSplitter:根据 AST(编译器的抽象句法树)切分代码,保证代码功能片段完整;
  • SemanticSplitterNodeParser:根据语义相关性对将文本切分为片段。

索引(Indexing)与检索(Retrieval)

基础概念:在「检索」相关的上下文中,「索引」即index, 通常是指为了实现快速检索而设计的特定「数据结构」。

构建索引

可以直接在内存中构建一个索引

# 构建 index
index = VectorStoreIndex(nodes)

获取 retriever 

# 获取 retriever
vector_retriever = index.as_retriever(
    similarity_top_k=2 # 返回前两个结果
)

检索

# 检索
results = vector_retriever.retrieve("白酒价格")

show_json(results[0]) # 有多个结果,这里展示第一个

输出

{
    "node": {
        "id_": "dc661086-ff9f-4560-8ac2-483b81223f80",
        "embedding": null,
        "metadata": {
            "file_path": "D:\\Code\\Python\\Hello\\AI\\01\\data\\spyl.pdf",
            "file_name": "spyl.pdf",
            "file_type": "application/pdf",
            "file_size": 743694,
            "creation_date": "2024-06-25",
            "last_modified_date": "2024-06-25",
            "total_pages": 8,
            "source": "3"
        },
        "excluded_embed_metadata_keys": [
            "file_name",
            "file_type",
            "file_size",
            "creation_date",
            "last_modified_date",
            "last_accessed_date"
        ],
        "excluded_llm_metadata_keys": [
            "file_name",
            "file_type",
            "file_size",
            "creation_date",
            "last_modified_date",
            "last_accessed_date"
        ],
        "relationships": {
            "1": {
                "node_id": "39abd1b8-3353-4632-895a-981cd7f609ad",
                "node_type": "4",
                "metadata": {
                    "file_path": "D:\\Code\\Python\\Hello\\AI\\01\\data\\spyl.pdf",
                    "file_name": "spyl.pdf",
                    "file_type": "application/pdf",
                    "file_size": 743694,
                    "creation_date": "2024-06-25",
                    "last_modified_date": "2024-06-25",
                    "total_pages": 8,
                    "source": "3"
                },
                "hash": "f81084b2e6112000a1faa64be0e87691c8203ac9815168ec92debfbcfcc38206",
                "class_name": "RelatedNodeInfo"
            },
            "2": {
                "node_id": "fa922781-5a5d-4df5-92a8-fb8389adc2d6",
                "node_type": "1",
                "metadata": {
                    "file_path": "D:\\Code\\Python\\Hello\\AI\\01\\data\\spyl.pdf",
                    "file_name": "spyl.pdf",
                    "file_type": "application/pdf",
                    "file_size": 743694,
                    "creation_date": "2024-06-25",
                    "last_modified_date": "2024-06-25",
                    "total_pages": 8,
                    "source": "3"
                },
                "hash": "ff2511e76d50da6f4387b69836bb5bff8f5686ea58dbdc691975d4f1cc3dc9ae",
                "class_name": "RelatedNodeInfo"
            },
            "3": {
                "node_id": "466cb2c0-3cfb-4e84-8c67-f8b052d007a7",
                "node_type": "1",
                "metadata": {},
                "hash": "43b2a8d2583cf7feaa14902ec3df94cc28c691bdf37bc67c5daf34da80e610d4",
                "class_name": "RelatedNodeInfo"
            }
        },
        "text": "2.1 白酒价格 \n截至6 月23 日,飞天原箱、飞天散瓶批价分别为2420 元、2140 元,周环比分别下\n降180 元、150 元;普五批价965 元、1573 批价880 元,周环比基本平稳。 \n \n图2 飞天茅台、普五、1573 批发价格走势 \n \n-5.01%\n-1.30%\n-7%\n-6%\n-5%\n-4%\n-3%\n-2%\n-1%\n0%\n1%\n2%\n3%\n电子(申万)\n通信(申万)\n建筑装饰(申万)\n石油石化(申万)\n汽车(申万)\n银行(申万)\n交通运输(申万)\n非银金融(申万)\n环保(申万)\n有色金属(申万)\n机械设备(申万)\n公用事业(申万)\n计算机(申万)\n基础化工(申万)\n建筑材料(申万)\n国防军工(申万)\n煤炭(申万)\n医药生物(申万)\n电力设备(申万)\n美容护理(申万)\n钢铁(申万)\n家用电器(申万)\n农林牧渔(申万)\n纺织服饰(申万)\n轻工制造(申万)\n社会服务(申万)\n综合(申万)",
        "mimetype": "text/plain",
        "start_char_idx": 330,
        "end_char_idx": 738,
        "text_template": "{metadata_str}\n\n{content}",
        "metadata_template": "{key}: {value}",
        "metadata_seperator": "\n",
        "class_name": "TextNode"
    },
    "score": 0.7363739872707532,
    "class_name": "NodeWithScore"
}

Process finished with exit code 0

排在第一个的往往是最匹配的搜索结果,当然向量检索,关键词检索各有各的优缺点,实际生产使用一般两者结合,会结合两者分别匹配出来的结果进行重排序然后输出。

使用自定义的 Vector Store,以 Chroma 为例

import chromadb
from chromadb.config import Settings

from llama_index.vector_stores.chroma import ChromaVectorStore

def gen_index():
    chroma_client = chromadb.PersistentClient(settings=Settings(allow_reset=True))
    try:
        chroma_collection = chroma_client.create_collection("demo")
        vector_store = ChromaVectorStore(chroma_collection)
        storage_context = StorageContext.from_defaults(vector_store=vector_store)
        nodes = gen_nodes()
        index = VectorStoreIndex(nodes, storage_context=storage_context)
        storage_context.persist("./data")
    except:
        chroma_collection = chroma_client.get_collection("demo")
        vector_store = ChromaVectorStore(chroma_collection=chroma_collection)
        # index = VectorStoreIndex.from_vector_store(vector_store)
        storage_context = StorageContext.from_defaults(persist_dir="./data", vector_store=vector_store)
        index = load_index_from_storage(storage_context)
    return index

以上代码把通过 chromadb 创建了一个 demo 的 collection,并通过 ChromaVectorStore 实例化了一个向量存储,index 创建的时候除了传入 nodes,还需要传入 storage_context ,用于将内存中的数据实例化到数据库以及 ./data 目录中,下次运行就不用再去切割 pdf,而是通过 load_index_from_storage(storage_context) 从盘中加载到内存中,速度要快很多。

这个过程我们封装成函数 gen_index 这样更方便调用

通过 index 检索:

def query(question):
    index = gen_index()
    vector_retriever = index.as_retriever()
    res = vector_retriever.retrieve(question)
    for node in res:
        show_json(node)

上面代码封装了检索,但是这个结果是以向量搜索得到的排序,可能不是最优的,可以对搜索后的结果进一步排序处理,这里使用 SentenceTransformerRerank 进行重排序

def query(question):
    index = gen_index()
    vector_retriever = index.as_retriever()
    res = vector_retriever.retrieve(question)
    postprocessor = SentenceTransformerRerank(
        model="BAAI/bge-reranker-large", top_n=2
    )
    res = postprocessor.postprocess_nodes(res, query_str=question)
    for node in res:
        show_json(node)

Chat Engine

接下来只需要简单几行代码就可以实现问答机器人了

def chat():
    index = gen_index()
    chat_engine = index.as_chat_engine(llm=OpenAI(temperature=0, model="gpt-3.5-turbo"))
    while 1:
        query = input("请输入查询:")
        if query == "exit":
            break
        query = f"你是证券分析方面的专家,根据用户的问题回答,使用中文回答。用户问题:{query}"
        streaming_response = chat_engine.stream_chat(query) # 流式输出
        for token in streaming_response.response_gen:
            print(token, end="")


if __name__ == "__main__":
    chat()

以上输出不同的模型输出可能会有差异,但表达的信息基本是从 pdf 中出来的。

---------------------补充--------------------------

上面的 Chat Engine 的例子过于简单,忽略了重排序,这样的 chat engine 在一些情况下是回答不好问题的,虽然看上去能用。

接下来我们把重排序的逻辑加上再进行 chat

def chat():
    index = gen_index()

    # 定义检索后排序模型
    reranker = SentenceTransformerRerank(
        model="BAAI/bge-reranker-large", top_n=2
    )
    # 定义 RAG Fusion 检索器
    fusion_retriever = QueryFusionRetriever(
        [index.as_retriever()],
        similarity_top_k=5, # 检索召回 top k 结果
        num_queries=3, # 生成 query 数
        use_async=True
    )
    # 构建单轮 query engine
    query_engine = RetrieverQueryEngine(
        retriever=fusion_retriever,
        node_postprocessors=[reranker]
    )

....

上面代码修正了 query_engine 的构建方式,加入了重排序模型

接下来构建 chat engine

....
    text_qa_template = """
    你是证券分析方面的专家,结合给出的参考知识,使用中文回答。\n
    参考内容如下:\n
    ---------------------\n
    {context_str}\n
    ---------------------\n
    问题: {query_str}\n
    回答: 
    """
    text_qa_template = PromptTemplate(text_qa_template)
    # chat_engine = index.as_chat_engine(
    #     llm=OpenAI(temperature=0, model="gpt-3.5-turbo"),
    #     text_qa_template=text_qa_template,
    #     verbose=True
    # )
    chat_engine = CondenseQuestionChatEngine.from_defaults(
        query_engine=query_engine,
        condense_question_prompt=text_qa_template
    )
    # 这里为何查询的时候输入是英文?
    while 1:
        query = input("\n请输入查询:")
        if query == "exit":
            break
        streaming_response = chat_engine.stream_chat(query)
        for token in streaming_response.response_gen:
            print(token, end="")
            if token == '。':
                print('\n')

上面我们修改了 chat engine 的构建方式,不是简单粗暴直接 index.as_chat_engine 了

--------------------补充 end---------------------------

如果有疑问,欢迎私信探讨

<think>我们正在处理用户的问题:"请问LlamaIndex 使用方法及示例教程"。根据之前的对话历史,用户已经询问过LlamaIndex支持的数据库类型,现在转向询问使用方法和示例教程。 根据提供的引用,我们可以总结出以下关键点: 引用[1]:使用LLM进行高效查询,包括环境配置、创建查询引擎,结合向量存储、总结索引和工具检索器。 引用[2]:构建聊天引擎,包括加载数据、创建索引、配置聊天引擎,以及通过中专API调用大模型。 引用[3]:构建私有知识库的保姆级教程,包括数据注入、结构化(索引构建)、访问(检索)的完整RAG实现。 引用[4]:从基础智能体到RAG文档检索的分步指南,包括前期准备(配置OpenAI API环境)和代码实现。 引用[5]:结合本地模型(如通过Ollama)的入门教程,包括安装依赖项。 因此,我们可以将回答组织为以下几个部分: 1. 环境配置(安装和设置) 2. 加载数据与创建索引 3. 构建查询引擎(基本查询) 4. 构建聊天引擎(对话式交互) 5. 构建RAG应用(文档检索) 6. 结合本地模型(如Ollama) 每个部分提供简要说明和代码示例。 注意:由于用户之前的问题是关于数据库的,我们可以在示例中适当结合之前提到的数据库(如使用PostgreSQL作为向量存储),但重点在于LlamaIndex的基本使用流程。 另外,根据系统指令,我们需要在适当的地方添加引用标识,并且代码块要正确。 最后,生成相关问题。 开始构建回答:</think>### LlamaIndex 使用方法及示例教程 LlamaIndex一个强大的 LLM 数据框架,专为私有知识库构建、RAG 应用和智能代理开发设计。以下是核心使用流程及代码示例,涵盖数据加载、索引构建、查询引擎和聊天引擎实现[^3][^4]: --- #### 一、环境配置与安装 ```bash # 基础安装 pip install llama-index python-dotenv # 扩展支持(向量库/本地模型) pip install llama-index-vector-stores-chroma # Chroma向量库 pip install llama-index-llms-ollama # Ollama本地模型支持[^5] ``` #### 二、核心使用流程 ##### 1. 数据加载与索引构建 ```python from llama_index.core import VectorStoreIndex, SimpleDirectoryReader from llama_index.vector_stores.chroma import ChromaVectorStore import chromadb # 加载本地文档(支持PDF/TXT/HTML等) documents = SimpleDirectoryReader("data").load_data() # 创建Chroma向量库 chroma_client = chromadb.PersistentClient(path="./chroma_db") vector_store = ChromaVectorStore(chroma_collection=chroma_client.create_collection("knowledge")) index = VectorStoreIndex.from_documents(documents, vector_store=vector_store) # 自动生成嵌入向量[^3] ``` ##### 2. 基础查询引擎 ```python query_engine = index.as_query_engine() response = query_engine.query("LlamaIndex如何优化检索效率?") print(response) # 输出:LlamaIndex通过向量索引和分层筛选... [^1] ``` ##### 3. 聊天引擎实现(对话式交互) ```python from llama_index.core.memory import ChatMemoryBuffer memory = ChatMemoryBuffer.from_defaults(token_limit=1500) chat_engine = index.as_chat_engine( chat_mode="context", # 上下文感知模式 memory=memory, system_prompt="你是一个技术文档助手,用简洁语言回答" ) # 多轮对话 print(chat_engine.chat("RAG是什么?")) # 解释RAG概念 print(chat_engine.chat("用Python示例说明")) # 自动关联上文生成代码[^2] ``` ##### 4. 自定义检索器(混合搜索) ```python from llama_index.core.retrievers import VectorIndexRetriever from llama_index.core.query_engine import RetrieverQueryEngine # 同时使用向量+关键词检索 vector_retriever = VectorIndexRetriever(index=index, similarity_top_k=3) keyword_retriever = index.as_retriever(retriever_mode="keyword") hybrid_retriever = HybridRetriever([vector_retriever, keyword_retriever]) query_engine = RetrieverQueryEngine.from_args(hybrid_retriever) ``` --- #### 三、进阶应用示例 ##### 1. RAG 文档检索系统 ```python # 结合工具调用的智能体 from llama_index.core.tools import QueryEngineTool from llama_index.agent.openai import OpenAIAgent tool = QueryEngineTool.from_defaults(query_engine=query_engine) agent = OpenAIAgent.from_tools([tool], verbose=True) # 执行复杂任务 agent.chat("总结data/目录下所有PDF中关于向量数据库的内容,并对比Chroma和Milvus") ``` ##### 2. 本地模型集成(Ollama) ```python from llama_index.llms.ollama import Ollama from llama_index.embeddings.huggingface import HuggingFaceEmbedding # 使用本地LLM和嵌入模型 llm = Ollama(model="llama3", request_timeout=60.0) embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-small-zh") index = VectorStoreIndex.from_documents(documents, embed_model=embed_model, llm=llm) # [^5] ``` --- ### 四、最佳实践 1. **索引优化** - 大型数据集使用 `SentenceSplitter` 分块(建议 512 tokens) - 添加元数据过滤:`index.storage_context.persist(persist_dir="./storage")` 2. **性能调优** ```python # 加速检索 index.as_query_engine( similarity_top_k=5, # 减少召回数量 response_mode="tree_summarize" # 分层总结结果 ) ``` 3. **错误处理** ```python try: response = query_engine.query("非法指令@@") except Exception as e: print(f"查询失败: {str(e)}") # 捕获LLM格式错误 ``` > ⚙️ **部署提示**:生产环境建议使用 `FastAPI` 封装引擎,搭配 `PGVector` 实现高并发访问[^3][^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值