标签: LangChain

  • Ollama 与 LangChain构建本地化且强大的 LLM 生态系统

    在大型语言模型(LLM)的快速发展中,Ollama 将继续简化本地部署流程,帮助开发者更加便捷地运行 LLM,而 LangChain 将扩展更多数据源和功能模块,帮助开发者构建更加丰富、复杂的 AI 应用。

    1. LangChain:构建 LLM 应用的强大框架

    LangChain 是一个用于构建 LLM 驱动的应用程序的开发框架,它提供了一系列强大的工具和组件,使得开发者能够轻松构建出复杂的、数据驱动的应用。LangChain 支持与各种外部数据源、API 和工具的集成,极大地扩展了 LLM 的应用场景。

    LangChain 的核心功能包括多种提示管理、链式调用、数据增强等,能够帮助开发者构建更加智能、灵活的 AI 应用,如智能问答、聊天机器人、文档分析系统等。

    LangChain 的特点

    1. 丰富的组件与工具:LangChain 提供了提示模板(Prompt Templates)、链式调用(Chains)、智能体(Agents)等多种组件,帮助开发者实现复杂的功能。
    2. 数据集成:LangChain 可以与多种数据源集成,包括文件、数据库、向量数据库、Web API 等,扩展了 LLM 的应用范围。
    3. 应用开发能力:开发者可以通过 LangChain 构建复杂的应用,如问答系统、聊天机器人、数据增强应用等,为实际业务提供智能支持。
    4. 会话记忆管理:LangChain 支持多轮对话和会话记忆,使得开发者能够创建更加自然的对话流和用户交互体验。

    2. Ollama:简化本地 LLM 部署

    Ollama 是一个工具平台,旨在简化本地 LLM 的部署过程。它为用户提供了一个简单、直观的方式,让开发者能够快速在本地计算机上运行各种开源的 LLM,无需复杂的配置或环境搭建。通过 Ollama,开发者可以轻松下载、安装并运行大多数流行的 LLM,从而降低了 LLM 使用的技术门槛。

    Ollama 的特点

    1. 简洁易用的命令行工具:通过简短的命令即可下载并启动 LLM,极大简化了模型的部署流程。
    2. 本地运行,隐私保障:Ollama 允许用户在本地计算机上运行模型,避免了将数据上传至云端的隐私风险。
    3. 灵活的模型管理:用户可以方便地下载、管理并切换多个不同的 LLM,例如 LLaMA、Mistral、Gemma 等,满足不同应用需求。
    4. 跨平台支持:Ollama 支持 macOS、Linux 和部分 Windows 系统,确保各种开发环境都能顺利使用。

    3. Ollama与LangChain的协同作用

    虽然 Ollama 和 LangChain 各自有独立的功能,但它们实际上是互为补充的工具,可以在多个开发场景中协同工作,帮助开发者更高效地利用 LLM 技术。

    例如,开发者可以在本地使用 Ollama 运行 LLAMA 模型,然后结合 LangChain 构建一个智能问答系统,该系统能够与外部数据源(如本地文件或数据库)交互。Ollama 提供了本地模型的运行环境,而 LangChain 则帮助开发者设计和实现复杂的应用逻辑。

    4. 应用场景

    场景Ollama 角色LangChain 角色
    本地文档问答系统提供本地运行的 LLM 推理能力管理文档解析、嵌入、问答流程
    离线智能助理本地运行模型(如LLAMA)处理会话管理、记忆、工具调用
    多模型测试与对比快速切换多个 LLM 进行测试提供统一接口进行多模型测试

    通过将 Ollama 与 LangChain 结合,开发者不仅能够在本地高效运行 LLM,还能够快速构建复杂的 LLM 应用,充分发挥 LLM 的能力。

  • 基于LangChain和Ollama的本地文档问答系统

    使用 LangChain 框架和 Ollama 开源大模型搭建一个问答系统,根据提供的文档内容回答用户提出的问题。

    系统主要由以下几个部分组成:

    • 文档加载模块: 负责从指定的路径加载文档。
    • 文档切分模块: 将加载的文档按照指定的大小和重叠度进行切分,以便 LLM 处理。
    • LLM 加载模块: 负责加载指定的 Ollama 模型。
    • 问答链创建模块: 使用 LangChain 表达式语言 (LCEL) 构建问答链,将用户问题和文档内容输入到 LLM 中,并解析 LLM 的输出。
    • 提问模块: 接收用户输入的问题,调用问答链生成答案,并返回给用户。
    • 重试机制: 使用 Tenacity 库,当提问模块出现错误时,自动进行重试,以提高系统的稳定性。

    1. 创建一个虚拟环境,名字为langqa

    conda create -n langqa python=3.12

    2. 激活虚拟环境

    conda activate langqa

    3. 安装依赖

    pip install langchain langchain_community langchain-ollama ollama tenacity

    4. 部署代码

    替换为你自己的文件、模型和地址

    • 文件:tcpdump.1-4.4.0.txt
    • 模型:llama3.1:8b
    • OLLAMA :http://localhost:11434

    配置完成后使用命令行进行运行对话

    python langqa.py

    代码

    """
    Author: Qixinlee
    Description: 基于LangChain和Ollama的本地文档问答系统
    """ 
    
    import os
    from langchain_community.document_loaders import TextLoader
    from langchain.text_splitter import RecursiveCharacterTextSplitter
    from langchain_ollama import OllamaLLM
    from langchain.prompts import PromptTemplate
    import ollama
    from tenacity import retry, stop_after_attempt, wait_random_exponential
    from langchain_core.runnables import chain
    from langchain_core.output_parsers import StrOutputParser
    
    # 常量定义
    DOCUMENT_PATH = os.path.join(os.path.dirname(__file__), "tcpdump.1-4.4.0.txt")
    CHUNK_SIZE = 1000
    CHUNK_OVERLAP = 100
    LLM_MODEL_NAME = "llama3.1:8b"
    OLLAMA_HOST = "http://localhost:11434"
    
    # 1. 设置 Ollama 连接信息
    os.environ["OLLAMA_HOST"] = OLLAMA_HOST
    ollama.DEFAULT_BASE_URL = OLLAMA_HOST
    
    # 2. 加载文档
    def load_document(document_path: str):
        try:
            loader = TextLoader(document_path)
            documents = loader.load()
            print(f"Successfully loaded document from {document_path}")
            return documents
        except Exception as e:
            print(f"Error loading document: {e}")
            exit()
    
    # 3. 切分文档
    def split_document(documents, chunk_size: int, chunk_overlap: int):
        text_splitter = RecursiveCharacterTextSplitter(chunk_size=chunk_size, chunk_overlap=chunk_overlap)
        texts = text_splitter.split_documents(documents)
        return texts
    
    # 4. 加载 LLM
    def load_llm(llm_model_name: str):
        try:
            llm = OllamaLLM(model=llm_model_name)
            print(f"Successfully loaded LLM model: {llm_model_name}")
            return llm
        except Exception as e:
            print(f"Error loading LLM model: {e}")
            exit()
    
    # 5. 创建问答链 (使用 LangChain 表达式语言)
    def create_qa_chain(llm):
        try:
            template = """你是一个问答机器人。请根据以下已知信息,用简洁和专业的中文回答用户的问题。
            如果无法从中得到答案,请清晰地输出 “根据已知信息无法回答该问题”。
    
            已知信息:
            {context}
    
            问题: {question}
            答案:"""
            QA_CHAIN_PROMPT = PromptTemplate(
                input_variables=["context", "question"], template=template
            )
    
            # 使用 Runnable 序列
            qa_chain = QA_CHAIN_PROMPT | llm | StrOutputParser()
    
            print("Successfully created QA chain.")
            return qa_chain
        except Exception as e:
            print(f"Error creating QA chain: {e}")
            exit()
    
    # 6. 提问 (使用 Tenacity 实现重试机制)
    @retry(stop=stop_after_attempt(3), wait=wait_random_exponential(multiplier=1, min=4, max=10))
    def generate_answer(qa_chain, document_content: str, query: str):
        try:
            result = qa_chain.invoke({"context": document_content, "question": query})
            print("Successfully generated answer.")
            return result
        except Exception as e:
            print(f"Error during QA: {e}")
            raise
    
    # 主程序
    if __name__ == "__main__":
    
        # 1. 加载文档
        documents = load_document(DOCUMENT_PATH)
    
        # 2. 切分文档
        texts = split_document(documents, CHUNK_SIZE, CHUNK_OVERLAP)
    
        # 3. 加载 LLM (使用常量)
        llm = load_llm(LLM_MODEL_NAME)
    
        # 4. 将所有文本块连接成一个字符串
        document_content = "\n".join([text.page_content for text in texts])
    
        # 5. 创建问答链
        qa_chain = create_qa_chain(llm)
    
        # 6. 循环提问
        while True:
            query = input("请输入你的问题 (输入 'exit' 退出): ")
            if query.lower() == "exit":
                break
    
            try:
                result = generate_answer(qa_chain, document_content, query)
                print("Question (中文):", query)
                print("Answer (中文):", result)
    
            except Exception as e:
                print(f"Failed to generate answer: {e}")
                exit()