分类: AI

  • 使用 Podman 部署 Cockpit 和 Immich 机器学习容器

    使用 Podman 部署安装 Cockpit 管理工具并使用 Podman 启动 Immich 的机器学习容器。以便在浏览器中方便配置和访问

    一、开放所需端口

    在默认情况下,Linux 防火墙(firewalld)可能会阻止一些端口的外部访问。为了确保 Cockpit 和 Immich 模块能够正常被访问,需要永久放行相关端口。

    1. 放行 9090 端口(用于 Cockpit)

    firewall-cmd --add-port=9090/tcp --permanent
    firewall-cmd --reload

    2. 放行 3003 端口(用于 Immich 机器学习容器)

    firewall-cmd --permanent --add-port=3003/tcp
    firewall-cmd --reload

    二、安装 Cockpit 和 Podman

    Cockpit 是一款轻量级的 Web 管理工具,可用于查看系统信息、容器、服务等。

    dnf install podman cockpit cockpit-podman -y

    安装完成后,启用并启动 Cockpit:

    systemctl enable --now cockpit.socket

    然后可通过浏览器访问 Cockpit:

    https://<你的服务器IP>:9090

    注意:首次访问时浏览器可能提示 SSL 证书不安全,可选择“继续前往”。

    三、部署 Immich Machine Learning 容器

    Immich 是一个支持自动图片整理、面部识别等功能的自托管照片管理系统。我们配置immich的远程机器学习提高计算速度

    1. 下载镜像

    podman pull ghcr.io/immich-app/immich-machine-learning:release

    2. 运行容器

    podman run \
      --name immich_machine_learning \
      --restart=always \
      --replace \
      -p 3003:3003 \
      -v model-cache:/cache \
      -e TZ=Asia/Shanghai \
      -d \
      ghcr.io/immich-app/immich-machine-learning:release

    此命令的作用如下:

    • --name: 指定容器名称
    • --restart=always: 容器自动重启策略
    • --replace: 替换已有同名容器
    • -p 3003:3003: 映射本地端口
    • -v model-cache:/cache: 使用持久卷缓存模型
    • -e TZ=Asia/Shanghai: 设置时区
    • -d: 后台运行容器

    四、配置容器开机自动启动(可选但推荐)

    虽然运行容器时使用了 --restart=always,但 Podman 默认并不会像 Docker 一样在系统启动时自动重启容器。要实现真正的“开机自启”,需依赖 systemd 启动服务。

    1. 生成并安装 systemd 单元文件

    podman generate systemd --name immich_machine_learning --files --restart-policy=always

    这将在当前目录生成 container-immich_machine_learning.service 文件。将其移动到系统服务目录并启用:

    mv container-immich_machine_learning.service /etc/systemd/system/
    systemctl daemon-reexec
    systemctl enable container-immich_machine_learning.service

    五、验证部署

    • 访问 Cockpit Web 控制台查看容器状态:
      https://<你的服务器IP>:9090
    • 访问 Immich ML 控制台查看容器状态:
      http://<你的服务器IP>:3003

  • 使用 llama.cpp 打造你的专属本地大语言模型服务

    是否曾想过拥有一个完全私有、无需联网、响应迅速的个人 AI 助手?大语言模型(LLM)在各种任务中的表现令人惊艳,但它们通常依赖强大的 GPU 和云计算资源。llama.cpp 的出现,为本地运行 LLM 提供了一种全新可能:无需昂贵显卡,也无需连接互联网,我们也能在个人电脑上畅快使用大模型。

    llama.cpp 是一个由 Georgi Gerganov 开发的开源项目,它彻底改变了我们在本地设备上运行大型语言模型 (LLM) 的方式。它以 C/C++ 编写,并针对 CPU 进行了高度优化,使得许多原本需要强大 GPU 才能运行的复杂模型,现在也能在个人电脑上流畅运行,包括 macOS、Windows 和 Linux 系统。

    llama.cpp 提供了两种主要的使用方式

    • 命令行界面 (CLI)
    • Server Web UI

    一、命令行界面(CLI):极简高效的交互方式

    CLI (Command Line Interface)llama.cpp 最基础也是最核心的交互方式。它让你能直接通过终端命令来加载模型并进行文本生成。

    特点与优势

    • 直接控制: CLI 提供了对模型运行参数最直接的控制。你可以精确调整上下文长度、温度、重复惩罚等参数,以微调模型的输出行为。
    • 资源效率: 作为 CPU 优化项目,CLI 模式通常具有非常高的资源效率,尤其是在内存和处理速度方面。
    • 脚本化友好: 对于开发者或高级用户来说,CLI 命令可以轻松集成到 shell 脚本中,实现自动化任务或批处理。
    • 快速测试: 如果你只想快速测试一个模型或进行简单的交互,CLI 是最快的入门方式。

    典型使用场景

    • 模型功能与性能基准测试: 快速加载不同模型版本,评估其在特定任务上的表现和资源消耗。
    • 自动化文本生成: 在 CI/CD 流程中集成 LLM 的文本生成能力,例如自动生成代码注释、测试用例或文档草稿。
    • 特定任务微调前的数据生成: 利用模型生成大量特定格式的文本数据,用于后续的数据集构建或模型训练。
    • 离线批量处理: 对大量输入数据进行 LLM 推理,无需网络连接或复杂的服务器架构。

    如何使用

    1. 加载模型并进行交互式对话:
    ./llama-cli -m path/to/your/model.gguf -i

    llama-cli是主程序,-m 指定模型路径,-i 启用交互模式

    1. 一次性生成文本:
    ./llama-cli -m path/to/your/model.gguf -p "请给我讲一个关于未来的短故事。" -n 256

    -p 提供初始提示,-n指定生成最大 token 数量

    二、Server Web UI:图形化体验与本地 API 服务

    Server Web UIllama.cpp 提供的另一种高级功能,它将模型封装成一个本地 HTTP 服务器,并允许通过 Web 浏览器或其他应用程序与之交互。这种方式为用户提供了更友好、更直观的图形界面,并扩展了模型的应用范围。

    特点与优势

    • 用户友好界面: 无需命令行知识,普通用户也能通过直观的网页界面与模型进行对话,就像使用 ChatGPT 一样。
    • API 接口: 服务器提供与 OpenAI API 兼容的 RESTful API,这意味着许多为 OpenAI 模型设计的第三方工具、应用程序和前端界面可以直接连接到你的本地 llama.cpp 服务器。
    • 可扩展性: 通过 API,你可以轻松地将本地 LLM 集成到自己的应用程序、聊天机器人或自动化流程中,而无需深入了解 llama.cpp 的底层实现。
    • 多用户或多会话支持: 服务器模式通常可以更好地管理并发请求,适合同时处理多个用户或多个独立的对话会话。

    典型使用场景

    • 个人 AI 助理: 搭建一个私有的本地聊天机器人,用于日常交流、写作辅助、知识查询等。
    • 开发者工具: 作为本地 LLM 后端,供开发中的应用程序调用,用于测试、原型设计等。
    • 桌面应用集成: 任何需要 LLM 能力的桌面应用都可以通过连接到本地 llama-server 来获取支持。

    如何使用

    1. 启动 llama-server
    ./llama-server -m path/to/your/model.gguf

    默认情况下,服务器会在 http://127.0.0.1:8080 上启动。

    1. 通过 Web 浏览器访问:
      服务器启动后,你可以在浏览器中打开 http://127.0.0.1:8080 来访问 llama.cpp 提供的基本 Web UI。
  • 使用远程服务器加速 Immich 的机器学习推理

    为了显著提升 Immich 在执行照片和视频分析等任务时的机器学习推理性能,可以将 Immich 的机器学习容器部署在具备更强硬件性能(例如配备高性能 GPU 或专用 AI 加速卡的服务器)的远程服务器上。这种方式可以将计算密集型的推理工作负载从运行 Immich Server 的主服务器卸载,从而释放主服务器的资源并加快推理速度。

    1. 确保版本一致性

    重要提示

    1. Immich 服务器(即运行 Immich Web、API 和 Microservices 的主服务器)的版本必须与您计划在远程服务器上部署的机器学习服务容器的版本完全一致
    2. 如果这两个组件的版本不匹配,极有可能导致各种不可预期的错误、功能异常,甚至推理任务的彻底失败。为了确保系统的稳定性和功能的正常运行,请务必仔细核对并保持版本同步。

    2. 在远程系统上部署机器学习容器

    在您选定的远程服务器上,创建一个名为 docker-compose.yml 的文件。该文件将定义并配置 Immich 机器学习服务的 Docker 容器。请根据您的远程服务器的硬件配置以及您希望使用的加速后端选择合适的配置:

    name: immich_remote_ml
    
    services:
      immich-machine-learning:
        container_name: immich_machine_learning
        # For hardware acceleration, add one of -[armnn, cuda, rocm, openvino, rknn] to the image tag.
        # Example tag: ${IMMICH_VERSION:-release}-cuda
        image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
        # extends:
        #   file: hwaccel.ml.yml
        #   service: # set to one of [armnn, cuda, rocm, openvino, openvino-wsl, rknn] for accelerated inference - use the `-wsl` version for WSL2 where applicable
        volumes:
          - model-cache:/cache
        restart: always
        ports:
          - 3003:3003
    
    volumes:
      model-cache:

    3. 启动容器

    在远程服务器上执行以下命令启动服务:

    docker compose up -d

    4. 配置 Immich 使用远程推理服务

    在 Immich Web 界面中:

    • 进入 系统设置
    • 打开 系统管理 > 设置 > 机器学习设置
    • 将远程服务器的机器学习服务 URL 填入(例如:http://<远程服务器IP>:3003

    完成以上配置后,Immich Server 在需要进行机器学习推理时,例如人脸识别、物体识别、场景分类等,将会自动将这些请求发送到您配置的远程机器学习服务。这将利用远程服务器更强大的计算资源来加速推理过程,从而提升 Immich 的整体性能和用户体验。您可以通过观察 Immich 的任务队列和远程服务器的资源使用情况来验证远程推理是否正常工作。

  • IT 模型与 PT 模型的区别解析:指令微调与量化感知训练的应用

    在大模型领域,模型的不同训练阶段和量化技术影响了其性能、推理速度、资源需求等方面。以下将详细解析 IT 模型PT 模型IT-QAT 模型PT-QAT 模型 的区别

    1. IT 模型 (Instruction Tuning 模型)

    • 含义: IT 模型是在基础的预训练模型基础上,使用特定的指令数据集进行微调,从而增强模型对任务指令的理解与执行能力。
    • 目标: 通过对指令进行微调,使模型在处理带有指令的任务时,能够更好地理解和响应。这使得 IT 模型在问答、对话生成、任务执行等方面表现更好。
    • 特点:
    • 微调方式: 在预训练的基础上进行指令微调,增强模型的任务理解能力。
    • 性能: 在需要理解和执行特定任务指令的场景中,表现更加优异。
    • 适用场景: 主要用于需要理解并执行指令的任务,如智能助手、问答系统等。
    • 资源需求: 由于没有经过量化,模型可能较大,推理速度较慢,特别是在资源受限的环境下。

    2. PT 模型 (Pre-Training 模型)

    • 含义: PT 模型是未经指令微调的基础预训练模型。它通常在海量的文本数据上进行训练,学习语言的统计规律和基本的语义理解能力。
    • 目标: 构建一个通用的语言理解和生成模型,具备广泛的语言知识,但不专门针对某些特定任务进行优化。
    • 特点:
    • 训练方式: 仅经过基础的预训练,未进行任何特定任务的微调。
    • 性能: 拥有广泛的知识和语言能力,但在复杂任务中的表现可能不如 IT 模型。
    • 适用场景: 适用于通用的文本生成任务,但在需要执行复杂指令或高度定制任务时可能表现较差。
    • 资源需求: 相对较高,特别是在处理大规模数据时,模型体积较大。

    3. IT-QAT 模型 (Instruction Tuning – Quantization Aware Training 模型)

    • 含义: IT-QAT 模型是在 IT 模型的基础上,结合了量化感知训练(QAT)技术,将模型压缩为较小尺寸,适用于资源受限的环境。
    • 目标: 在 IT 模型的指令微调能力的基础上,通过量化感知训练(QAT)减小模型的存储需求,提升推理速度,尤其是在 CPU 上的推理效率。
    • 特点:
    • 微调与量化: 结合了指令微调和量化感知训练,先对模型进行指令微调,然后进行量化训练,减小模型尺寸。
    • 性能: 由于 QAT 技术,模型在量化后尽量保留性能,能够在资源受限的环境中快速推理。
    • 适用场景: 在低内存、高并发任务中,适用于需要指令执行能力的场景,如低资源环境下的智能代理、问答系统等。
    • 资源需求: 模型体积较小,推理速度较快,适合 CPU 推理或低端设备上运行。

    4. PT-QAT 模型 (Pre-Training – Quantization Aware Training 模型)

    • 含义: PT-QAT 模型是基于预训练模型,通过量化感知训练(QAT)技术对模型进行压缩,优化了资源受限环境下的推理性能。
    • 目标: 在预训练的基础上,通过量化感知训练减少模型大小并提升推理效率,适用于没有经过指令微调的通用语言任务。
    • 特点:
    • 训练与量化: 仅经过预训练,没有进行指令微调,但在训练过程中使用 QAT 技术进行量化,减小模型体积。
    • 性能: 在通用语言任务中,性能依然不错,但相比 IT 模型,可能在执行指令型任务时表现较差。
    • 适用场景: 适用于资源受限环境下的通用语言任务,如文本生成、语言建模等,特别是在需要优化模型大小和推理速度的场景。
    • 资源需求: 模型体积较小,适合低资源设备,推理速度较快,但没有指令理解能力。

    对比

    特性IT 模型PT 模型IT-QAT 模型PT-QAT 模型
    训练阶段预训练 + 指令微调仅预训练预训练 + 指令微调 + 量化感知训练仅预训练 + 量化感知训练
    指令理解能力一般一般
    模型大小相对较大相对较大较小 (量化)较小 (量化)
    资源需求相对较高相对较高低(经过量化优化)低(经过量化优化)
    推理速度可能较慢可能较慢较快(量化后优化)较快(量化后优化)
    适用场景需要指令理解的任务(问答、对话生成等)通用语言生成任务资源受限环境下的指令型任务(如问答、对话)资源受限环境下的通用语言任务(如文本生成)
    格式通常为标准权重格式(如 PyTorch)通常为标准权重格式(如 PyTorch)优化后的格式,适合低资源环境优化后的格式,适合低资源环境

    通过对 IT 模型PT 模型IT-QAT 模型PT-QAT 模型 的分析,可以看到每种模型都有其独特的优缺点。IT 模型适合那些需要高度定制指令理解的应用,而 PT 模型 则适用于通用语言生成任务。对于资源受限的环境,IT-QAT 模型PT-QAT 模型 通过量化感知训练显著降低了模型体积和资源需求,提升了推理速度。

  • 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()