partitech/php-mistral

连接到 MistralAi 推理或 Llama.cpp

v0.07 2024-04-02 11:41 UTC

This package is auto-updated.

Last update: 2024-09-12 21:49:14 UTC


README

Mistral PHP 客户端是一个全面的 PHP 库,旨在与 Mistral AI API 交互。

此客户端支持 Mistral 平台和 Llama.cpp 用于本地测试和开发。

API 与主 Mistral API 相同

功能

  • 聊天完成:使用 Mistral 的语言模型生成对话响应和完成对话提示。
  • 聊天完成流:建立聊天完成的实时流,非常适合需要持续交互的应用程序。
  • 嵌入:获取文本的数值向量表示,使语义搜索、聚类和其他机器学习应用程序成为可能。
  • 填充中间:通过设置起始提示和可选后缀来自动生成代码,允许模型在中间完成代码。非常适合在预定义边界内创建特定的代码段。

入门

要开始在项目中使用 Mistral PHP 客户端,请确保您的系统上已安装 PHP。此客户端库与 PHP 8.3 及更高版本兼容。

安装

要安装 Mistral PHP 客户端,请运行以下命令

composer require partitech/php-mistral

使用

要在您的 PHP 应用程序中使用客户端,您需要导入软件包并使用您的 API 密钥初始化一个新的客户端实例。

您可以在 示例 目录中查看完整示例。

与 La plateforme 的聊天消息

use Partitech\PhpMistral\MistralClient;
use Partitech\PhpMistral\Messages;

$apiKey = 'YOUR_PRIVATE_MISTRAL_KEY';
$client = new MistralClient($apiKey);

$messages = new Messages();
$messages->addUserMessage('What is the best French cheese?');
$result = $client->chat($messages,
    [
        'model' => 'mistral-large-latest',
        'temperature' => 0.7,
        'top_p' => 1,
        'max_tokens' => 16,
        'safe_prompt' => false,
        'random_seed' => null
    ]
);
print_r($result->getMessage());

注意,您可以使用以下内容填充聊天讨论

$messages->addSystemMessage('Add system Message');
$messages->addAssistantMessage('Any response');
$messages->addUserMessage('What is the best French cheese?');
$messages->addAssistantMessage('Any response');

要使用 Lama.cpp 本地推理获得相同的结果

use Partitech\PhpMistral\LamaCppClient;
use Partitech\PhpMistral\Messages;

$apiKey = 'YOUR_PRIVATE_MISTRAL_KEY';
$client = new LamaCppClient($apiKey, 'https://:8080');

$messages = new Messages();
$messages->addUserMessage('What is the best French cheese?');
$result = $client->chat($messages);
print_r($result->getMessage());

与 La plateforme 使用流响应进行聊天

use Partitech\PhpMistral\MistralClient;
use Partitech\PhpMistral\Messages;

$apiKey = 'YOUR_PRIVATE_MISTRAL_KEY';
$client = new MistralClient($apiKey, 'https://:8080');

$messages = new Messages();
$messages->addUserMessage('What is the best French cheese?');
$params = [
        'model' => 'mistral-large-latest',
        'temperature' => 0.7,
        'top_p' => 1,
        'max_tokens' => 16,
        'safe_prompt' => false,
        'random_seed' => null
];
foreach ($client->chatStream($messages, $params)) as $chunk) {
    echo $chunk->getChunk();
}

与 Lama.cpp 使用流响应进行聊天

use Partitech\PhpMistral\LamaCppClient;
use Partitech\PhpMistral\Messages;

$apiKey = 'YOUR_PRIVATE_MISTRAL_KEY';
$client = new LamaCppClient($apiKey, 'https://:8080');

$messages = new Messages();
$messages->addUserMessage('What is the best French cheese?');
foreach ($client->chatStream($messages) as $chunk) {
    echo $chunk->getChunk();
}

使用 La plateform 进行嵌入

$apiKey = 'YOUR_PRIVATE_MISTRAL_KEY';
$strings = ['Hello', 'World', 'Hello World'];

$client = new MistralClient($apiKey);
$embeddings = $client->embeddings($strings);
print_r($embeddings);

结果

Array
(
    [id] => bfb5a084be3e4659bd67234e0e8a2dae
    [object] => list
    [data] => Array
        (
            [0] => Array
                (
                    [object] => embedding
                    [embedding] => Array
                        (
                            [0] => -0.024917602539062
                            ...
                            [1023] => -0.024826049804688
                        )

                    [index] => 0
                )

            [1] => Array
                (
                    [object] => embedding
                    [embedding] => Array
                        (
                            [0] => -0.010711669921875
                            ...
                            [1023] => -0.04107666015625
                        )

                    [index] => 1
                )

            [2] => Array
                (
                    [object] => embedding
                    [embedding] => Array
                        (
                            [0] => 0.0004112720489502
                            ...
                            [1023] => -0.032379150390625
                        )

                    [index] => 2
                )

        )

    [model] => mistral-embed
    [usage] => Array
        (
            [prompt_tokens] => 10
            [total_tokens] => 10
            [completion_tokens] => 0
        )

)

使用 Lama.cpp 服务器进行嵌入

$apiKey = 'YOUR_PRIVATE_MISTRAL_KEY';
$strings = ['Hello', 'World', 'Hello World'];

$client = new LamaCppClient($apiKey, 'https://:8080');
$embeddings = $client->embeddings($strings);
print_r($embeddings);

结果

Array
(
    [data] => Array
        (
            [0] => Array
                (
                    [embedding] => Array
                        (
                    [0] => 3.5081260204315
                    ...
                    [4095] => -2.5789933204651
                )
            [1] => Array
            ...

        )

   
)

填充中间

$prompt  = "Write response in php:\n";
$prompt .= "/** Calculate date + n days. Returns \DateTime object */";
$suffix  = 'return $datePlusNdays;\n}';

try {
    $result = $client->fim(
        prompt: $prompt,
        suffix: $suffix,
        params:[
            'model' => $model_name,
            'temperature' => 0.7,
            'top_p' => 1,
            'max_tokens' => 200,
            'min_tokens' => 0,
            'stop' => 'string',
            'random_seed' => 0
        ]
    );
} catch (MistralClientException $e) {
    echo $e->getMessage();
    exit(1);
}

结果

function datePlusNdays(\DateTime $date, $n) {
 $datePlusNdays = clone $date;
 $datePlusNdays->add(new \DateInterval('P'.abs($n).'D'));

以流模式填充中间

try {
    $result = $client->fimStream(
        prompt: $prompt,
        suffix: $suffix,
        params:[
            'model' => $model_name,
            'temperature' => 0.7,
            'top_p' => 1,
            'max_tokens' => 200,
            'min_tokens' => 0,
            'stop' => 'string',
            'random_seed' => 0
        ]
    );
    foreach ($result as $chunk) {
        echo $chunk->getChunk();
    }
} catch (MistralClientException $e) {
    echo $e->getMessage();
    exit(1);
}

结果

function datePlusNdays(\DateTime $date, $n) {
 $datePlusNdays = clone $date;
 $datePlusNdays->add(new \DateInterval('P'.abs($n).'D'));

Pixtral 请求

$contents = [
    ['type' => 'text', 'text' => 'Describe this image in detail please.'],
    ['type' => 'image_url', 'image_url' => 'https://s3.amazonaws.com/cms.ipressroom.com/338/files/201808/5b894ee1a138352221103195_A680%7Ejogging-edit/A680%7Ejogging-edit_hero.jpg'],
    ['type' => 'text', 'text' => 'and this one as well. Answer in French.'],
    ['type' => 'image_url', 'image_url' => 'https://www.wolframcloud.com/obj/resourcesystem/images/a0e/a0ee3983-46c6-4c92-b85d-059044639928/6af8cfb971db031b.png']
];

$messages = new Messages();
$messages->addMixedContentUserMessage($contents);

try {
    $result = $client->chat(
        $messages,
        [
            'model' => 'Pixtral-12B-2409',
            'max_tokens' => 1024,
        ]
    );
} catch (MistralClientException $e) {
    echo $e->getMessage();
    exit(1);
}

print($result->getMessage());

结果

Dans cette image, on voit une famille de cinq personnes posant pour une photo. Ils sont tous vêtus de chemises rouges assorties et sont allongés sur le ventre sur une surface blanche devant un fond blanc. Les membres de la famille sourient et semblent être dans une pose détendue et joyeuse, les mains jointes devant eux. La famille semble former un groupe uni et heureux, et l'ambiance générale de la photo est chaleureuse et accueillante.

Lama.cpp 推理

MistralAi La plateforme 非常便宜,您应该考虑订阅它而不是运行本地的 Lama.cpp 实例。在我们的测试期间,此套餐仅花费我们 0.02€。如果您确实需要本地服务器,以下是一个您可以使用例如的 docker-compose

services:
  server:
    image: ghcr.io/ggerganov/llama.cpp:full
    volumes:
      - ./Llm/models:/models
    ports:
      - '8080:8080'
    environment:
      - CHAT_MODEL
      - MISTRAL_API_KEY
    command: ["--server", "-m", "/models/${CHAT_MODEL}", "-c", "4500", "--host", "0.0.0.0", "--api-key", "${MISTRAL_API_KEY}", "-ngl", "99", "-t", "10", "-v", "--embedding"]
    extra_hosts:
      - "host.docker.internal:host-gateway"

与 .env 文件

MISTRAL_API_KEY=that_is_a_very_mysterious_key
CHAT_MODEL=mistral-7b-instruct-v0.2.Q4_K_M.gguf

vLLM 推理

vLLMMistralAi La plateforme 的官方推理替代品。从 v0.6.0 开始,vLLM 与 mistral 的 plateforme 的 tools/tool_choice 完全兼容。要获取本地的 ISO 实例,您需要指定模板: examples/tool_chat_template_mistral.jinja。以下是一个您可以使用例如的 docker-compose

vLLM 为 tool_call 推理

services:
  mistral:
    image: vllm/vllm-openai:v0.6.0
    command: |
      --model mistralai/Mistral-Nemo-Instruct-2407
      --served-model-name nemo
      --max-model-len 32000
      --tensor-parallel-size 2
      --gpu-memory-utilization 1
      --trust-remote-code
      --enforce-eager
      --enable-auto-tool-choice
      --tool-call-parser mistral
      --chat-template /config/tool_chat_template_mistral.jinja
    environment:
      - HUGGING_FACE_HUB_TOKEN=*****
      - NVIDIA_VISIBLE_DEVICES=0,1
      - VLLM_WORKER_MULTIPROC_METHOD=spawn
    volumes:
      - /path_to_config/:/config
      - /path_to_cache/.cache/huggingface:/root/.cache/huggingface
    ports:
      - "40001:8000"
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              capabilities: [gpu]
    runtime: nvidia
    ipc: host
    networks:
      - llm_1x2_network
networks:
  llm_1x2_network:
    driver: bridge

vLLM 为 Pixtral 推理

services:
  mistral:
    image: vllm/vllm-openai:v0.6.1
    command: |
      --model mistralai/Pixtral-12B-2409 
      --tokenizer_mode mistral 
      --limit_mm_per_prompt 'image=4' 
      --max_num_batched_tokens 16384
      --served-model-name Pixtral-12B-2409 
      --max-model-len 16384
      --tensor-parallel-size 2
      --gpu-memory-utilization 1
      --trust-remote-code
      --enforce-eager
    environment:
      - HUGGING_FACE_HUB_TOKEN=*****
      - NVIDIA_VISIBLE_DEVICES=0,1
      - VLLM_WORKER_MULTIPROC_METHOD=spawn
    volumes:
      - /path_to_config/:/config
      - /path_to_cache/.cache/huggingface:/root/.cache/huggingface
    ports:
      - "40001:8000"
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              capabilities: [gpu]
    runtime: nvidia
    ipc: host
    networks:
      - llm_1x2_network
networks:
  llm_1x2_network:
    driver: bridge

关于响应对象

$client->chat() 方法返回一个 Partitech\PhpMistral\Response 对象。

$client = new MistralClient($apiKey);
$result = $client->chat(
        $messages,
        [
            'model' => 'mistral-large-latest',
            'temperature' => 0.7,
            'top_p' => 1,
            'max_tokens' => 250,
            'safe_prompt' => false,
            'random_seed' => null
        ]
    );

可用的方法有

$result->getChunk()
$result->getId()
$result->getChoices()
$result->getCreated()
$result->getGuidedMessage()
$result->getModel()
$result->getObject()
$result->getObject()
$result->getToolCalls()
$result->getUsage()

所有这些方法都是对服务器基本响应的访问器

{
    "id": "cmpl-e5cc70bb28c444948073e77776eb30ef",
    "object": "chat.completion",
    "created": 1702256327,
    "model": "mistral-large-latest",
    "choices":
    [
        {
            "index": 0,
            "message":
            {
                "role": "assistant",
                "content": "",
                "tool_calls":
                [
                    {
                        "function":
                        {
                            "name": "get_current_weather",
                            "arguments": "{\"location\": \"Paris, 75\"}"
                        }
                    }
                ]
            },
            "finish_reason": "tool_calls"
        }
    ],
    "usage":
    {
        "prompt_tokens": 118,
        "completion_tokens": 35,
        "total_tokens": 153
    }
}

方法名称和响应 JSON 是可理解的,但以下是一个基本解释

  • 从服务器获取最后一条消息响应。实际上,它从消息类获取最后一条消息,这是一个消息列表。
$result->getMessage()

示例

France is known for its diverse and high-quality cheeses, so it's challenging to single out one as the "best" because it largely depends on personal preference. However, some French cheeses are particularly renowned ...
  • 当使用流式响应时,它会获取服务器提供消息的最后一块。
foreach ($client->chatStream($messages, $params) as $chunk) {
    echo $chunk->getChunk();
}

示例

France is known 
  • 从服务器获取id的响应
$result->getId()

示例

cmpl-e5cc70bb28c444948073e77776eb30ef
  • 从服务器获取带有选项响应的数组对象
$result->getChoices()

示例

ArrayObject Object
(
    [storage:ArrayObject:private] => Array
        (
            [0] => Partitech\PhpMistral\Message Object
                (
                    [role:Partitech\PhpMistral\Message:private] => assistant
                    [content:Partitech\PhpMistral\Message:private] => France is known for its diverse and high-quality cheeses, so it's challenging to single out one as the "best" because it largely depends on personal preference. However, some French cheeses are particularly renowned:

1. Comté: This is a hard cheese made from unpasteurized cow's milk in the Franche-Comté region of eastern France. It has a nutty, slightly sweet flavor.

2. Brie de Meaux: Often just called Brie, this is a soft cheese with a white, edible rind. It's known for its creamy texture and mild, slightly earthy flavor.

3. Roquefort: This is a blue cheese made from sheep's milk. It has a strong, tangy flavor and is crumbly in texture.

4. Camembert: This is another soft cheese with a white, edible rind. It's similar to Brie but has a stronger, more pungent flavor.

5. Reblochon: This is a soft, washed-rind cheese from the Savoie region of France. It has a nutty
                    [chunk:Partitech\PhpMistral\Message:private] => 
                    [toolCalls:Partitech\PhpMistral\Message:private] => 
                )

        )

)

  • 获取创建响应的日期(整数时间戳)
$result->getCreated()

示例

1702256327
  • 获取引导消息对象。这是从vllm服务器返回的json_decoded消息。仅用于vllm服务器。
$result->getGuidedMessage()

示例

object(stdClass)#1 (1) {
  ["foo"]=>
  string(3) "bar"
}
  • 从服务器响应中获取使用的模型
$result->getModel()

示例

mistral-large-latest
  • 从服务器响应中获取对象索引
$result->getObject()

示例

chat.completion
  • 从服务器响应中获取tool_calls值。这是一个包含服务器json_decoded响应的关联数组。
$result->getToolCalls()

示例

$toolCall = $chatResponse->getToolCalls();
$functionName = $toolCall[0]['function']['name'];
$functionParams = $toolCall[0]['function']['arguments'];

// Call the proper function
$functionResult = $namesToFunctions[$functionName]($functionParams);

print_r($functionResult);
//    Array
//    (
//        [status] => Paid
//    )
  • 从服务器获取使用响应
$result->getUsage() 

示例

(
    [prompt_tokens] => 10
    [total_tokens] => 260
    [completion_tokens] => 250
)

文档

有关Mistral AI API和可用端点的详细文档,请参阅Mistral AI API文档

贡献

欢迎贡献!如果您想为项目做出贡献,请fork存储库,并提交包含您更改的pull请求。

许可证

Mistral PHP客户端是开源软件,根据MIT许可证授权。

支持

如果您遇到任何问题或需要帮助,请在GitHub存储库问题跟踪器中提交问题。

谢谢

此Readme.md主要复制自https://github.com/Gage-Technologies/mistral-go。感谢他们 :)