Skip to content

Commit e38cb0d

Browse files
authored
feat: add support for Hugging Face Inference API (#279)
* 1st Commit: Christopher * 2nd Commit: Claude Desktop with Jetbrains MCP: > I'm writing a PHP library that is similar to langchain but should also cover the HuggingFace inference API - like their library. You can access my terminal and my IDE via tools. Please have a look at the different tasks that should be available in src/Bridge/HuggingFace/Task.php and see the example implementation in examples/huggingface/text-classification.php in combination with the namespace PhpLlm\LlmChain\Bridge\HuggingFace. Your task is to implement the response conversion, corresponding DTOs and examples for all other tasks than text-classification. * 3rd Commit: Claude Desktop with Jetbrains MCP: > please have a look at the other examples in the examples/ folder using audio, image or text input and refactor the ones you just created. all new example files are located in /home/christopher/Projects/PHP-LLM/llm-chain/examples/huggingface - please verify they're working by executing them - and patch bugs if there are any * 4th Commit: Claude Desktop with Jetbrains MCP: > please create an example runner for huggingface examples, based on the /example file in root directory * 5th Commit: Christopher making it work.
1 parent 99336fe commit e38cb0d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1572
-5
lines changed

.env

+3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ AZURE_OPENAI_KEY=
2525
AZURE_LLAMA_BASEURL=
2626
AZURE_LLAMA_KEY=
2727

28+
# Hugging Face Access Token
29+
HUGGINGFACE_KEY=
30+
2831
# For using OpenRouter
2932
OPENROUTER_KEY=
3033

Makefile

+4
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ coverage:
2323

2424
run-examples:
2525
./example
26+
./huggingface
27+
28+
make huggingface-models:
29+
php examples/huggingface/_model-listing.php
2630

2731
ci: ci-stable
2832

README.md

+53-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# LLM Chain
22

3-
PHP library for building LLM-based features and applications.
3+
PHP library for building LLM-based and AI-based features and applications.
44

5-
This library is not a stable yet, but still rather experimental. Feel free to try it out, give feedback, ask questions, contribute or share your use cases.
6-
Abstractions, concepts and interfaces are not final and potentially subject of change.
5+
This library is not a stable yet, but still rather experimental. Feel free to try it out, give feedback, ask questions,
6+
contribute or share your use cases. Abstractions, concepts and interfaces are not final and potentially subject of change.
77

88
## Requirements
99

@@ -25,15 +25,16 @@ See [examples](examples) folder to run example implementations using this librar
2525
Depending on the example you need to export different environment variables
2626
for API keys or deployment configurations or create a `.env.local` based on `.env` file.
2727

28-
To run all examples, use `make run-examples` or `php example`.
28+
To run all examples, use `make run-examples` or `php example` and `php huggingface` for all HuggingFace related examples.
2929

3030
For a more sophisticated demo, see the [Symfony Demo Application](https://github.com/php-llm/symfony-demo).
3131

3232
## Basic Concepts & Usage
3333

3434
### Models & Platforms
3535

36-
LLM Chain categorizes two main types of models: **Language Models** and **Embeddings Models**.
36+
LLM Chain categorizes two main types of models: **Language Models** and **Embeddings Models**. On top of that, there are
37+
other models, like text-to-speech, image generation or classification models that are also supported.
3738

3839
Language Models, like GPT, Claude and Llama, as essential centerpiece of LLM applications
3940
and Embeddings Models as supporting models to provide vector representations of text.
@@ -71,6 +72,8 @@ $embeddings = new Embeddings();
7172
* Other Models
7273
* [OpenAI's Dall·E](https://platform.openai.com/docs/guides/image-generation) with [OpenAI](https://platform.openai.com/docs/overview) as Platform
7374
* [OpenAI's Whisper](https://platform.openai.com/docs/guides/speech-to-text) with [OpenAI](https://platform.openai.com/docs/overview) and [Azure](https://learn.microsoft.com/azure/ai-services/openai/concepts/models) as Platform
75+
* All models provided by [HuggingFace](https://huggingface.co/) can be listed with `make huggingface-models`
76+
And more filtered with `php examples/huggingface/_model-listing.php --provider=hf-inference --task=object-detection`
7477

7578
See [issue #28](https://github.com/php-llm/llm-chain/issues/28) for planned support of other models and platforms.
7679

@@ -725,6 +728,51 @@ final class MyProcessor implements OutputProcessor, ChainAwareProcessor
725728
}
726729
```
727730
731+
## HuggingFace
732+
733+
LLM Chain comes out of the box with an integration for [HuggingFace](https://huggingface.co/) which is a platform for
734+
hosting and sharing all kind of models, including LLMs, embeddings, image generation and classification models.
735+
736+
You can just instantiate the Platform with the corresponding HuggingFace bridge and use it with the `task` option:
737+
```php
738+
use PhpLlm\LlmChain\Bridge\HuggingFace\Model;
739+
use PhpLlm\LlmChain\Bridge\HuggingFace\PlatformFactory;
740+
use PhpLlm\LlmChain\Bridge\HuggingFace\Task;
741+
use PhpLlm\LlmChain\Model\Message\Content\Image;
742+
743+
$platform = PlatformFactory::create($apiKey);
744+
$model = new Model('facebook/detr-resnet-50');
745+
746+
$image = Image::fromFile(dirname(__DIR__, 2).'/tests/Fixture/image.jpg');
747+
$response = $platform->request($model, $image, [
748+
'task' => Task::OBJECT_DETECTION, // defining a task is mandatory for internal request & response handling
749+
]);
750+
751+
dump($response->getContent());
752+
```
753+
754+
#### Code Examples
755+
756+
1. [Audio Classification](examples/huggingface/audio-classification.php)
757+
1. [Automatic Speech Recognition](examples/huggingface/automatic-speech-recognition.php)
758+
1. [Chat Completion](examples/huggingface/chat-completion.php)
759+
1. [Feature Extraction (Embeddings)](examples/huggingface/feature-extraction.php)
760+
1. [Fill Mask](examples/huggingface/fill-mask.php)
761+
1. [Image Classification](examples/huggingface/image-classification.php)
762+
1. [Image Segmentation.php](examples/huggingface/image-segmentation.php)
763+
1. [Image-to-Text](examples/huggingface/image-to-text.php)
764+
1. [Object Detection](examples/huggingface/object-detection.php)
765+
1. [Question Answering](examples/huggingface/question-answering.php)
766+
1. [Sentence Similarity](examples/huggingface/sentence-similarity.php)
767+
1. [Summarization](examples/huggingface/summarization.php)
768+
1. [Table Question Answering](examples/huggingface/table-question-answering.php)
769+
1. [Text Classification](examples/huggingface/text-classification.php)
770+
1. [Text Generation](examples/huggingface/text-generation.php)
771+
1. [Text-to-Image](examples/huggingface/text-to-image.php)
772+
1. [Token Classification](examples/huggingface/token-classification.php)
773+
1. [Translation](examples/huggingface/translation.php)
774+
1. [Zero-shot Classification](examples/huggingface/zero-shot-classification.php)
775+
728776
## Contributions
729777
730778
Contributions are always welcome, so feel free to join the development of this library. To get started, please read the
+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
use PhpLlm\LlmChain\Bridge\HuggingFace\ApiClient;
4+
use PhpLlm\LlmChain\Bridge\HuggingFace\Model;
5+
use Symfony\Component\Console\Command\Command;
6+
use Symfony\Component\Console\Input\InputInterface;
7+
use Symfony\Component\Console\Input\InputOption;
8+
use Symfony\Component\Console\Output\ConsoleOutput;
9+
use Symfony\Component\Console\SingleCommandApplication;
10+
use Symfony\Component\Console\Style\SymfonyStyle;
11+
12+
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
13+
14+
$app = (new SingleCommandApplication('HuggingFace Model Listing'))
15+
->setDescription('Lists all available models on HuggingFace')
16+
->addOption('provider', 'p', InputOption::VALUE_REQUIRED, 'Name of the inference provider to filter models by')
17+
->addOption('task', 't', InputOption::VALUE_REQUIRED, 'Name of the task to filter models by')
18+
->setCode(function (InputInterface $input, ConsoleOutput $output) {
19+
$io = new SymfonyStyle($input, $output);
20+
$io->title('HuggingFace Model Listing');
21+
22+
$provider = $input->getOption('provider');
23+
$task = $input->getOption('task');
24+
25+
$models = (new ApiClient())->models($provider, $task);
26+
27+
if (0 === count($models)) {
28+
$io->error('No models found for the given provider and task.');
29+
30+
return Command::FAILURE;
31+
}
32+
33+
$io->listing(
34+
array_map(fn (Model $model) => $model->getName(), $models)
35+
);
36+
37+
return Command::SUCCESS;
38+
})
39+
->run();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
use PhpLlm\LlmChain\Bridge\HuggingFace\Model;
4+
use PhpLlm\LlmChain\Bridge\HuggingFace\PlatformFactory;
5+
use PhpLlm\LlmChain\Bridge\HuggingFace\Task;
6+
use PhpLlm\LlmChain\Model\Message\Content\Audio;
7+
use Symfony\Component\Dotenv\Dotenv;
8+
9+
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
10+
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
11+
12+
if (empty($_ENV['HUGGINGFACE_KEY'])) {
13+
echo 'Please set the HUGGINGFACE_KEY environment variable.'.PHP_EOL;
14+
exit(1);
15+
}
16+
17+
$platform = PlatformFactory::create($_ENV['HUGGINGFACE_KEY']);
18+
$model = new Model('MIT/ast-finetuned-audioset-10-10-0.4593');
19+
$audio = Audio::fromFile(dirname(__DIR__, 2).'/tests/Fixture/audio.mp3');
20+
21+
$response = $platform->request($model, $audio, [
22+
'task' => Task::AUDIO_CLASSIFICATION,
23+
]);
24+
25+
dump($response->getContent());
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
use PhpLlm\LlmChain\Bridge\HuggingFace\Model;
4+
use PhpLlm\LlmChain\Bridge\HuggingFace\PlatformFactory;
5+
use PhpLlm\LlmChain\Bridge\HuggingFace\Task;
6+
use PhpLlm\LlmChain\Model\Message\Content\Audio;
7+
use Symfony\Component\Dotenv\Dotenv;
8+
9+
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
10+
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
11+
12+
if (empty($_ENV['HUGGINGFACE_KEY'])) {
13+
echo 'Please set the HUGGINGFACE_KEY environment variable.'.PHP_EOL;
14+
exit(1);
15+
}
16+
17+
$platform = PlatformFactory::create($_ENV['HUGGINGFACE_KEY']);
18+
$model = new Model('openai/whisper-large-v3');
19+
$audio = Audio::fromFile(dirname(__DIR__, 2).'/tests/Fixture/audio.mp3');
20+
21+
$response = $platform->request($model, $audio, [
22+
'task' => Task::AUTOMATIC_SPEECH_RECOGNITION,
23+
]);
24+
25+
echo $response->getContent().PHP_EOL;
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
use PhpLlm\LlmChain\Bridge\HuggingFace\Model;
4+
use PhpLlm\LlmChain\Bridge\HuggingFace\PlatformFactory;
5+
use PhpLlm\LlmChain\Bridge\HuggingFace\Task;
6+
use PhpLlm\LlmChain\Model\Message\Message;
7+
use PhpLlm\LlmChain\Model\Message\MessageBag;
8+
use Symfony\Component\Dotenv\Dotenv;
9+
10+
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
11+
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
12+
13+
if (empty($_ENV['HUGGINGFACE_KEY'])) {
14+
echo 'Please set the HUGGINGFACE_KEY environment variable.'.PHP_EOL;
15+
exit(1);
16+
}
17+
18+
$platform = PlatformFactory::create($_ENV['HUGGINGFACE_KEY']);
19+
$model = new Model('HuggingFaceH4/zephyr-7b-beta');
20+
21+
$messages = new MessageBag(Message::ofUser('Hello, how are you doing today?'));
22+
$response = $platform->request($model, $messages, [
23+
'task' => Task::CHAT_COMPLETION,
24+
]);
25+
26+
echo $response->getContent().PHP_EOL;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
use PhpLlm\LlmChain\Bridge\HuggingFace\Model;
4+
use PhpLlm\LlmChain\Bridge\HuggingFace\PlatformFactory;
5+
use PhpLlm\LlmChain\Bridge\HuggingFace\Task;
6+
use PhpLlm\LlmChain\Model\Response\VectorResponse;
7+
use Symfony\Component\Dotenv\Dotenv;
8+
9+
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
10+
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
11+
12+
if (empty($_ENV['HUGGINGFACE_KEY'])) {
13+
echo 'Please set the HUGGINGFACE_KEY environment variable.'.PHP_EOL;
14+
exit(1);
15+
}
16+
17+
$platform = PlatformFactory::create($_ENV['HUGGINGFACE_KEY']);
18+
$model = new Model('thenlper/gte-large');
19+
20+
$response = $platform->request($model, 'Today is a sunny day and I will get some ice cream.', [
21+
'task' => Task::FEATURE_EXTRACTION,
22+
]);
23+
24+
assert($response instanceof VectorResponse);
25+
26+
echo 'Dimensions: '.$response->getContent()[0]->getDimensions().PHP_EOL;

examples/huggingface/fill-mask.php

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
use PhpLlm\LlmChain\Bridge\HuggingFace\Model;
4+
use PhpLlm\LlmChain\Bridge\HuggingFace\PlatformFactory;
5+
use PhpLlm\LlmChain\Bridge\HuggingFace\Task;
6+
use Symfony\Component\Dotenv\Dotenv;
7+
8+
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
9+
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
10+
11+
if (empty($_ENV['HUGGINGFACE_KEY'])) {
12+
echo 'Please set the HUGGINGFACE_KEY environment variable.'.PHP_EOL;
13+
exit(1);
14+
}
15+
16+
$platform = PlatformFactory::create($_ENV['HUGGINGFACE_KEY']);
17+
$model = new Model('FacebookAI/xlm-roberta-base');
18+
19+
$response = $platform->request($model, 'Hello I\'m a <mask> model.', [
20+
'task' => Task::FILL_MASK,
21+
]);
22+
23+
dump($response->getContent());
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
use PhpLlm\LlmChain\Bridge\HuggingFace\Model;
4+
use PhpLlm\LlmChain\Bridge\HuggingFace\PlatformFactory;
5+
use PhpLlm\LlmChain\Bridge\HuggingFace\Task;
6+
use PhpLlm\LlmChain\Model\Message\Content\Image;
7+
use Symfony\Component\Dotenv\Dotenv;
8+
9+
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
10+
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
11+
12+
if (empty($_ENV['HUGGINGFACE_KEY'])) {
13+
echo 'Please set the HUGGINGFACE_KEY environment variable.'.PHP_EOL;
14+
exit(1);
15+
}
16+
17+
$platform = PlatformFactory::create($_ENV['HUGGINGFACE_KEY']);
18+
$model = new Model('google/vit-base-patch16-224');
19+
20+
$image = Image::fromFile(dirname(__DIR__, 2).'/tests/Fixture/image.jpg');
21+
$response = $platform->request($model, $image, [
22+
'task' => Task::IMAGE_CLASSIFICATION,
23+
]);
24+
25+
dump($response->getContent());
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
use PhpLlm\LlmChain\Bridge\HuggingFace\Model;
4+
use PhpLlm\LlmChain\Bridge\HuggingFace\PlatformFactory;
5+
use PhpLlm\LlmChain\Bridge\HuggingFace\Task;
6+
use PhpLlm\LlmChain\Model\Message\Content\Image;
7+
use Symfony\Component\Dotenv\Dotenv;
8+
9+
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
10+
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
11+
12+
if (empty($_ENV['HUGGINGFACE_KEY'])) {
13+
echo 'Please set the HUGGINGFACE_KEY environment variable.'.PHP_EOL;
14+
exit(1);
15+
}
16+
17+
$platform = PlatformFactory::create($_ENV['HUGGINGFACE_KEY']);
18+
$model = new Model('nvidia/segformer-b0-finetuned-ade-512-512');
19+
20+
$image = Image::fromFile(dirname(__DIR__, 2).'/tests/Fixture/image.jpg');
21+
$response = $platform->request($model, $image, [
22+
'task' => Task::IMAGE_SEGMENTATION,
23+
]);
24+
25+
dump($response->getContent());
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
use PhpLlm\LlmChain\Bridge\HuggingFace\Model;
4+
use PhpLlm\LlmChain\Bridge\HuggingFace\PlatformFactory;
5+
use PhpLlm\LlmChain\Bridge\HuggingFace\Task;
6+
use PhpLlm\LlmChain\Model\Message\Content\Image;
7+
use Symfony\Component\Dotenv\Dotenv;
8+
9+
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
10+
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
11+
12+
if (empty($_ENV['HUGGINGFACE_KEY'])) {
13+
echo 'Please set the HUGGINGFACE_KEY environment variable.'.PHP_EOL;
14+
exit(1);
15+
}
16+
17+
$platform = PlatformFactory::create($_ENV['HUGGINGFACE_KEY']);
18+
$model = new Model('Salesforce/blip-image-captioning-base');
19+
20+
$image = Image::fromFile(dirname(__DIR__, 2).'/tests/Fixture/image.jpg');
21+
$response = $platform->request($model, $image, [
22+
'task' => Task::IMAGE_TO_TEXT,
23+
]);
24+
25+
echo $response->getContent().PHP_EOL;
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
use PhpLlm\LlmChain\Bridge\HuggingFace\Model;
4+
use PhpLlm\LlmChain\Bridge\HuggingFace\PlatformFactory;
5+
use PhpLlm\LlmChain\Bridge\HuggingFace\Task;
6+
use PhpLlm\LlmChain\Model\Message\Content\Image;
7+
use Symfony\Component\Dotenv\Dotenv;
8+
9+
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
10+
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
11+
12+
if (empty($_ENV['HUGGINGFACE_KEY'])) {
13+
echo 'Please set the HUGGINGFACE_KEY environment variable.'.PHP_EOL;
14+
exit(1);
15+
}
16+
17+
$platform = PlatformFactory::create($_ENV['HUGGINGFACE_KEY']);
18+
$model = new Model('facebook/detr-resnet-50');
19+
20+
$image = Image::fromFile(dirname(__DIR__, 2).'/tests/Fixture/image.jpg');
21+
$response = $platform->request($model, $image, [
22+
'task' => Task::OBJECT_DETECTION,
23+
]);
24+
25+
dump($response->getContent());

0 commit comments

Comments
 (0)