llama的C++与Python集成指南

文章目录

  • 一、关于 llama-cpp-python
  • 二、安装
  • 安装配置
  • 支持的后端
  • Windows 笔记
  • MacOS笔记
  • 升级和重新安装
  • 三、高级API
  • 1、简单示例
  • 2、从 Hugging Face Hub 中提取模型
  • 3、聊天完成
  • 4、JSON和JSON模式
  • JSON模式
  • JSON Schema 模式
  • 5、函数调用
  • 6、多模态模型
  • 7、Speculative Decoding
  • 8、Embeddings
  • 9、调整上下文窗口
  • 四、OpenAI兼容Web服务器
  • Web服务器功能
  • 五、Docker镜像
  • 六、低级API
  • 七、发展
  • 八、常见问题解答
  • 是否有预构建的二进制/二进制轮子可用?
  • 这与llama. cpp`llama.cpp`相比如何?
  • 许可证

  • 一、关于 llama-cpp-python

    Python bindings for llama.cpp

  • github : https://github.com/abetlen/llama-cpp-python
  • 文档:https://llama-cpp-python.readthedocs.io/en/latest/

  • 简单的Python绑定**@ggerganov的** llama.cpp库。 该套餐提供:

  • 通过ctypes接口对C API的低级访问。
  • 类似OpenAI的API
  • 区块链兼容性
  • LlamaIndex兼容性
  • 本地副驾驶更换
  • 函数调用支持
  • 视觉API支持
  • 多种型号
  • 文件可在https://llama-cpp-python.readthedocs.io/en/latest查阅。


    二、安装

    要求:

  • Python 3.8+
  • Linux:gcc或clang
  • Windows:Visual Studio或MinGW
  • MacOS: Xcode

  • 要安装包,请运行:

    pip install llama-cpp-python
    

    这也将从源代码构建llama.cpp并将其与此python包一起安装。

    如果失败,请将--verbose添加到pip install中,请参阅完整的cmake构建日志。


    预制 Whell (新)

    也可以安装具有基本CPU支持的预构建轮子。

    pip install llama-cpp-python \
      --extra-index-url https://abetlen.github.io/llama-cpp-python/whl/cpu
    

    安装配置

    llama.cpp支持许多硬件加速后端以加速推理以及后端特定选项。有关完整列表,请参阅llama.cpp自述文件。

    所有llama.cppcmake构建选项都可以在安装过程中通过CMAKE_ARGS环境变量或--config-settings / -Ccli标志进行设置。


    环境变量

    # Linux and Mac
    CMAKE_ARGS="-DGGML_BLAS=ON -DGGML_BLAS_VENDOR=OpenBLAS" \
      pip install llama-cpp-python
    

    # Windows
    $env:CMAKE_ARGS = "-DGGML_BLAS=ON -DGGML_BLAS_VENDOR=OpenBLAS"
    pip install llama-cpp-python
    

    CLI / requirements.txt

    也可以通过 pip install -C / --config-settings 命令设置 和保存到 requirements.txt 文件:

    pip install --upgrade pip # ensure pip is up to date
    pip install llama-cpp-python \
      -C cmake.args="-DGGML_BLAS=ON;-DGGML_BLAS_VENDOR=OpenBLAS"
    

    # requirements.txt
    
    llama-cpp-python -C cmake.args="-DGGML_BLAS=ON;-DGGML_BLAS_VENDOR=OpenBLAS"
    

    支持的后端

    以下是一些常见的后端、它们的构建命令和所需的任何其他环境变量。

    OpenBLAS (CPU)
    To install with OpenBLAS, set the GGML_BLAS and GGML_BLAS_VENDOR environment variables before installing:

    CMAKE_ARGS="-DGGML_BLAS=ON -DGGML_BLAS_VENDOR=OpenBLAS" pip install llama-cpp-python
    

    CUDA、Metal、hipBLAS (ROCm)、Vulkan、SYCL、RPC 等,不一一列举


    Windows 笔记


    MacOS笔记

    详细的MacOS金属GPU安装留档可在docs/install/macos.md


    升级和重新安装

    要升级和重建llama-cpp-python,请添加--upgrade --force-reinstall --no-cache-dir标志到pip install命令以确保从源代码重建包。


    三、高级API

    API参考

    高级API通过Llama 类提供简单的托管接口。


    1、简单示例

    下面是一个简短的示例,演示了如何使用高级API来完成基本文本:

    from llama_cpp import Llama
    
    llm = Llama(
          model_path="./models/7B/llama-model.gguf",
          # n_gpu_layers=-1, # Uncomment to use GPU acceleration
          # seed=1337, # Uncomment to set a specific seed
          # n_ctx=2048, # Uncomment to increase the context window
    )
    output = llm(
          "Q: Name the planets in the solar system? A: ", # Prompt
          max_tokens=32, # Generate up to 32 tokens, set to None to generate up to the end of the context window
          stop=["Q:", "\n"], # Stop generating just before the model would generate a new question
          echo=True # Echo the prompt back in the output
    ) # Generate a completion, can also call create_completion
    print(output)
    

    默认情况下llama-cpp-python以OpenAI兼容格式生成完成:

    {
      "id": "cmpl-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "object": "text_completion",
      "created": 1679561337,
      "model": "./models/7B/llama-model.gguf",
      "choices": [
        {
          "text": "Q: Name the planets in the solar system? A: Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune and Pluto.",
          "index": 0,
          "logprobs": None,
          "finish_reason": "stop"
        }
      ],
      "usage": {
        "prompt_tokens": 14,
        "completion_tokens": 28,
        "total_tokens": 42
      }
    }
    

    可以通过Llama类的__call__create_completion方法完成文本。


    2、从 Hugging Face Hub 中提取模型

    您可以使用from_pretrained方法直接从 Hugging Face 下载gguf格式的Llama模型。
    您需要安装huggingface-hub软件包才能使用此功能(pip install huggingface-hub)。

    llm = Llama.from_pretrained(
        repo_id="Qwen/Qwen2-0.5B-Instruct-GGUF",
        filename="*q8_0.gguf",
        verbose=False
    )
    

    默认情况下from_pretrained会将模型下载到huggingface缓存目录,然后您可以使用huggingface-cli工具管理已安装的模型文件。


    3、聊天完成

    高级API还提供了一个简单的聊天完成界面。

    聊天完成要求模型知道如何将消息格式化为单个提示。 这个Llama类使用预先注册的聊天格式(即chatmlllama-2gemma等)或通过提供自定义聊天处理程序对象来实现这一点。


    该模型将使用以下优先顺序将消息格式化为单个提示:

  • 使用chat_handler如果提供
  • 使用chat_format如果提供
  • 使用tokenizer.chat_template来自gguf模型的元数据(应该适用于大多数新模型,旧模型可能没有这个)
  • 否则就回到llama-2聊天模式

  • 设置verbose=True以查看选定的聊天格式。

    from llama_cpp import Llama
    llm = Llama(
          model_path="path/to/llama-2/llama-model.gguf",
          chat_format="llama-2"
    )
    llm.create_chat_completion(
          messages = [
              {"role": "system", "content": "You are an assistant who perfectly describes images."},
              {
                  "role": "user",
                  "content": "Describe this image in detail please."
              }
          ]
    )
    

    可以通过Llama类的create_chat_completion方法完成聊天。

    对于OpenAI API v1兼容性,您可以使用create_chat_completion_openai_v1方法,该方法将返回pydatic模型而不是dicts。


    4、JSON和JSON模式

    要将聊天响应限制为仅有效的JSON或特定的JSON架构,请使用create_chat_completion中的response_format参数。


    JSON模式

    以下示例将仅将响应限制为有效的JSON字符串。

    from llama_cpp import Llama
    llm = Llama(model_path="path/to/model.gguf", chat_format="chatml")
    llm.create_chat_completion(
        messages=[
            {
                "role": "system",
                "content": "You are a helpful assistant that outputs in JSON.",
            },
            {"role": "user", "content": "Who won the world series in 2020"},
        ],
        response_format={
            "type": "json_object",
        },
        temperature=0.7,
    )
    

    JSON Schema 模式

    要将响应进一步限制为特定的JSON Schema,请将模式添加到response_format参数的schema属性中。

    from llama_cpp import Llama
    llm = Llama(model_path="path/to/model.gguf", chat_format="chatml")
    llm.create_chat_completion(
        messages=[
            {
                "role": "system",
                "content": "You are a helpful assistant that outputs in JSON.",
            },
            {"role": "user", "content": "Who won the world series in 2020"},
        ],
        response_format={
            "type": "json_object",
            "schema": {
                "type": "object",
                "properties": {"team_name": {"type": "string"}},
                "required": ["team_name"],
            },
        },
        temperature=0.7,
    )
    

    5、函数调用

    高级API支持OpenAI兼容的函数和工具调用。
    这可以通过functionary预训练模型聊天格式或通用chatml-function-calling聊天格式实现。

    from llama_cpp import Llama
    llm = Llama(model_path="path/to/chatml/llama-model.gguf", chat_format="chatml-function-calling")
    llm.create_chat_completion(
          messages = [
            {
              "role": "system",
              "content": "A chat between a curious user and an artificial intelligence assistant. The assistant gives helpful, detailed, and polite answers to the user's questions. The assistant calls functions with appropriate input when necessary"
    
            },
            {
              "role": "user",
              "content": "Extract Jason is 25 years old"
            }
          ],
          tools=[{
            "type": "function",
            "function": {
              "name": "UserDetail",
              "parameters": {
                "type": "object",
                "title": "UserDetail",
                "properties": {
                  "name": {
                    "title": "Name",
                    "type": "string"
                  },
                  "age": {
                    "title": "Age",
                    "type": "integer"
                  }
                },
                "required": [ "name", "age" ]
              }
            }
          }],
          tool_choice={
            "type": "function",
            "function": {
              "name": "UserDetail"
            }
          }
    )
    

    6、多模态模型

    llama-cpp-python支持诸如llava1.5之类的功能,它允许语言模型从文本和图像中读取信息。

    以下是支持的多模式模型及其各自的聊天处理程序(Python API)和聊天格式(Server API)。

    Model LlamaChatHandler chat_format
    llava-v1.5-7b Llava15ChatHandler llava-1-5
    llava-v1.5-13b Llava15ChatHandler llava-1-5
    llava-v1.6-34b Llava16ChatHandler llava-1-6
    moondream2 MoondreamChatHandler moondream2
    nanollava NanollavaChatHandler nanollava
    llama-3-vision-alpha Llama3VisionAlphaChatHandler llama-3-vision-alpha

    然后,您需要使用自定义聊天处理程序来加载剪辑模型并处理聊天消息和图像。

    from llama_cpp import Llama
    from llama_cpp.llama_chat_format import Llava15ChatHandler
    chat_handler = Llava15ChatHandler(clip_model_path="path/to/llava/mmproj.bin")
    llm = Llama(
      model_path="./path/to/llava/llama-model.gguf",
      chat_handler=chat_handler,
      n_ctx=2048, # n_ctx should be increased to accommodate the image embedding
    )
    llm.create_chat_completion(
        messages = [
            {"role": "system", "content": "You are an assistant who perfectly describes images."},
            {
                "role": "user",
                "content": [
                    {"type" : "text", "text": "What's in this image?"},
                    {"type": "image_url", "image_url": {"url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg" } }
                ]
            }
        ]
    )
    

    还可以使用from_pretrained方法从HugingFace Hub中提取模型。

    from llama_cpp import Llama
    from llama_cpp.llama_chat_format import MoondreamChatHandler
    
    chat_handler = MoondreamChatHandler.from_pretrained(
      repo_id="vikhyatk/moondream2",
      filename="*mmproj*",
    )
    
    llm = Llama.from_pretrained(
      repo_id="vikhyatk/moondream2",
      filename="*text-model*",
      chat_handler=chat_handler,
      n_ctx=2048, # n_ctx should be increased to accommodate the image embedding
    )
    
    response = llm.create_chat_completion(
        messages = [
            {
                "role": "user",
                "content": [
                    {"type" : "text", "text": "What's in this image?"},
                    {"type": "image_url", "image_url": {"url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg" } }
    
                ]
            }
        ]
    )
    print(response["choices"][0]["text"])
    

    注意:多模态模型还支持工具调用和JSON模式。

    def image_to_base64_data_uri(file_path):
        with open(file_path, "rb") as img_file:
            base64_data = base64.b64encode(img_file.read()).decode('utf-8')
            return f"data:image/png;base64,{base64_data}"
    
    # Replace 'file_path.png' with the actual path to your PNG file
    file_path = 'file_path.png'
    data_uri = image_to_base64_data_uri(file_path)
    
    messages = [
        {"role": "system", "content": "You are an assistant who perfectly describes images."},
        {
            "role": "user",
            "content": [
                {"type": "image_url", "image_url": {"url": data_uri }},
                {"type" : "text", "text": "Describe this image in detail please."}
            ]
        }
    ]
    

    7、Speculative Decoding

    llama-cpp-python支持推测解码,允许模型基于草稿模型生成完成。

    使用推测解码的最快方法是通过LlamaPromptLookupDecoding类。

    只需要在初始化的时候,传递这个 draft 模型到 Llama

    from llama_cpp import Llama
    from llama_cpp.llama_speculative import LlamaPromptLookupDecoding
    
    llama = Llama(
        model_path="path/to/model.gguf",
        draft_model=LlamaPromptLookupDecoding(num_pred_tokens=10) # num_pred_tokens is the number of tokens to predict 10 is the default and generally good for gpu, 2 performs better for cpu-only machines.
    )
    

    8、Embeddings

    生成文本嵌入,使用 create_embeddingembed
    注意,你需要传递 embedding=True 给构造器,在模型创建后,这些功能才能正常工作。

    import llama_cpp
    
    llm = llama_cpp.Llama(model_path="path/to/model.gguf", embedding=True)
    
    embeddings = llm.create_embedding("Hello, world!")
    
    # or create multiple embeddings at once
    
    embeddings = llm.create_embedding(["Hello, world!", "Goodbye, world!"])
    

    Transformer-style模型中的嵌入有两个主要概念:令牌级和序列级。序列级嵌入是通过将令牌级嵌入“池化”在一起产生的,通常是通过平均它们或使用第一个令牌。

    默认情况下,明确面向嵌入的模型通常会返回序列级嵌入,每个输入字符串一个。非嵌入模型(例如为文本生成设计的模型)通常只返回令牌级嵌入,每个序列中的每个令牌一个。因此,对于令牌级嵌入,返回类型的维度将更高。

    在某些情况下,可以使用模型创建时的pooling_type标志来控制池化行为。您可以使用LLAMA_POOLING_TYPE_NONE确保来自任何模型的令牌级嵌入。相反,获得面向生成的模型来产生序列级嵌入目前是不可能的,但您始终可以手动进行池化。


    9、调整上下文窗口

    Llama模型的上下文窗口决定了一次可以处理的最大令牌数量。默认情况下,这设置为512个令牌,但可以根据您的要求进行调整。

    例如,如果您想使用更大的上下文,您可以在初始化Llama对象时通过设置n_ctx参数来展开上下文窗口:

    llm = Llama(model_path="./models/7B/llama-model.gguf", n_ctx=2048)
    

    四、OpenAI兼容Web服务器

    llama-cpp-python提供了一个Web服务器,旨在作为OpenAI API的直接替代品。 这允许您将llama. cpp兼容模型与任何OpenAI兼容客户端(语言库、服务等)一起使用。

    要安装服务器包并开始使用:

    pip install 'llama-cpp-python[server]'
    python3 -m llama_cpp.server --model models/7B/llama-model.gguf
    

    与上面的硬件加速部分类似,您还可以安装支持GPU(cuBLAS)的产品,如下所示:

    CMAKE_ARGS="-DGGML_CUDA=on" FORCE_CMAKE=1 pip install 'llama-cpp-python[server]'
    python3 -m llama_cpp.server --model models/7B/llama-model.gguf --n_gpu_layers 35
    

    导航到http://localhost:8000/docs以查看OpenAPI留档。

    要绑定到0.0.0.0以启用远程连接,请使用python3 -m llama_cpp.server --host 0.0.0.0。 同样,要更改端口(默认为8000),请使用--port

    您可能还想设置提示格式。对于chat ml,使用

    python3 -m llama_cpp.server --model models/7B/llama-model.gguf --chat_format chatml
    

    这将根据模型期望的方式格式化提示。您可以在模型卡中找到提示格式。 有关可能的选项,请参阅llama_cpp/llama_chat_format.py并查找以“@register_chat_format”开头的行。

    如果安装了huggingface-hub,还可以使用--hf_model_repo_id标志从HuggingFace Hub加载模型。

    python3 -m llama_cpp.server --hf_model_repo_id Qwen/Qwen2-0.5B-Instruct-GGUF --model '*q8_0.gguf'
    

    Web服务器功能

  • 本地副驾驶更换
  • 函数调用支持
  • 视觉API支持
  • 多种型号

  • 五、Docker镜像

    Docker映像可在GHRC上获得。要运行服务器:

    docker run --rm -it -p 8000:8000 -v /path/to/models:/models -e MODEL=/models/llama-model.gguf ghcr.io/abetlen/llama-cpp-python:latest
    

    termux上的Docker(需要root)是目前唯一已知的在手机上运行它的方法,请参阅termux支持问题


    六、低级API

    API参考

    低级API是直接绑定到llama.cpp提供的C API的ctypes。 整个低级API可以在llama_cpp/llama_cpp.py中找到,并直接反映llama. h中的C API。

    下面是一个简短的示例,演示了如何使用低级API对提示进行标记:

    import llama_cpp
    import ctypes
    llama_cpp.llama_backend_init(False) # Must be called once at the start of each program
    params = llama_cpp.llama_context_default_params()
    # use bytes for char * params
    model = llama_cpp.llama_load_model_from_file(b"./models/7b/llama-model.gguf", params)
    ctx = llama_cpp.llama_new_context_with_model(model, params)
    max_tokens = params.n_ctx
    # use ctypes arrays for array params
    tokens = (llama_cpp.llama_token * int(max_tokens))()
    n_tokens = llama_cpp.llama_tokenize(ctx, b"Q: Name the planets in the solar system? A: ", tokens, max_tokens, llama_cpp.c_bool(True))
    llama_cpp.llama_free(ctx)
    

    查看示例文件夹以获取更多使用低级API的示例。


    七、发展

    该一揽子计划正在积极开发中,我欢迎任何贡献。

    要开始使用,请克隆存储库并以可编辑/开发模式安装包:

    git clone --recurse-submodules https://github.com/abetlen/llama-cpp-python.git
    cd llama-cpp-python
    
    # Upgrade pip (required for editable mode)
    pip install --upgrade pip
    
    # Install with pip
    pip install -e .
    
    # if you want to use the fastapi / openapi server
    pip install -e .[server]
    
    # to install all optional dependencies
    pip install -e .[all]
    
    # to clear the local build cache
    make clean
    

    您还可以测试lama.cpp的特定提交,方法是在vendor/llama.cpp子模块中签出所需的提交,然后再次运行make cleanpip install -e .llama.hAPI中的任何更改都需要 更改llama_cpp/llama_cpp.py文件以匹配新API(其他地方可能需要其他更改)。


    八、常见问题解答


    是否有预构建的二进制/二进制轮子可用?

    推荐的安装方法是从源代码安装,如上所述。 这样做的原因是llama.cpp是使用特定于您的系统的编译器优化构建的。 使用预构建的二进制文件需要禁用这些优化或为每个平台支持大量预构建的二进制文件。

    话虽如此,有一些预构建的二进制文件可通过版本以及一些社区提供的轮子获得。

    在未来,我愿意为通用平台提供预构建的二进制文件和轮子,我很乐意接受在这一领域的任何有用的贡献。 这目前正在跟踪#741


    这与llama. cppllama.cpp相比如何?

    我最初编写这个包是为了自己使用,有两个目标:

  • 提供一个简单的过程来安装llama.cpp并从Python访问llama.h中的完整C API
  • 提供高级Python API,可用作OpenAI API的直接替代品,以便可以轻松移植现有应用程序以使用llama.cpp
  • 对该一揽子计划的任何贡献和更改都将牢记这些目标。


    许可证

    该项目根据MIT许可条款获得许可。


    2024-07-16(二)

    作者:AI工程化

    物联沃分享整理
    物联沃-IOTWORD物联网 » llama的C++与Python集成指南

    发表回复