├── .gitignore ├── LICENSE ├── README.md ├── composer.json ├── composer.lock ├── data └── nobel_prize_physics_2024.pdf └── src ├── embedding.php ├── qa.php └── utility.php /.gitignore: -------------------------------------------------------------------------------- 1 | elastic-start-local 2 | vendor -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Build a RAG in PHP with LLPhant, Llama3.2 and Elasticsearch 2 | 3 | This is an example of **Retrieval-Augmented Generation (RAG)** in PHP using [LLPhant](https://github.com/theodo-group/LLPhant), [Llama 3.2](https://www.llama.com/) and [Elasticsearch](https://github.com/elastic/elasticsearch). 4 | 5 | To show the usage of a RAG system, we want Llama 3.2 answering to the following question: 6 | 7 | *Who won the Nobel Prize in Physics in 2024?* 8 | 9 | If we ask to Llama 3.2 this question the model will reply with a message as follows: 10 | 11 | *I don't have information on the 2024 Nobel Prize winners, as my knowledge cutoff is December 2023.* 12 | 13 | We will show how to augment the knowledge of Llama 3.2 using the RAG architecture. 14 | 15 | ## Install Llama3.2 16 | 17 | You can install [Llama 3.2](https://www.llama.com/) using [ollama](https://ollama.com/). 18 | 19 | For installing ollama on Linux, run the following command: 20 | 21 | ```bash 22 | curl -fsSL https://ollama.com/install.sh | sh 23 | ``` 24 | 25 | If you are using macOS or Windows use the [download](https://ollama.com/download) page. 26 | 27 | We suggest to install Llama3.2-1B or 3B that requires less CPU/GPU and RAM. 28 | 29 | For installing Llama3.2-3B use the following command: 30 | 31 | ```bash 32 | ollama run llama3.2:3b 33 | ``` 34 | 35 | You can start interacting to the LLama3.2 model using a chat. To exit, write `/bye` in the chat. 36 | 37 | ## Install Elasticsearch 38 | 39 | ```bash 40 | curl -fsSL https://elastic.co/start-local | sh 41 | ``` 42 | 43 | This script will install Elasticsearch and Kibana using a `docker-compose.yml` file stored in 44 | `elastic-start-local` folder. 45 | 46 | Elasticsearch and Kibana will run locally at http://localhost:9200 and http://localhost:5601. 47 | 48 | All the settings of Elasticsearch and Kibana are stored in the `elastic-start-local/.env` file. 49 | 50 | ## Install the RAG example 51 | 52 | You can install the PHP RAG example using [composer](https://getcomposer.org/), as follows: 53 | 54 | ```bash 55 | composer install 56 | ``` 57 | 58 | If you don't have composer installed you can download it from [here](https://getcomposer.org/download/). 59 | 60 | ## Add the Nobel Prize 2024 knowledge 61 | 62 | We need to store the knowledge about the Nobel Prize of 2024. We need to use a vector database for storing the 63 | [embeddings](https://www.elastic.co/what-is/vector-embedding), the mathematical representation of a sentence using an array of float numbers. 64 | 65 | If you are not familiar with the RAG architecture, you can watch [this introduction](https://www.youtube.com/watch?v=exQR-eXRDvU). 66 | 67 | The information about the Nobel Prize of 2024 is stored in a PDF file [data/nobel_prize_physics_2024.pdf](data/nobel_prize_physics_2024.pdf). This is PDF version of the content of this web page: 68 | https://www.nobelprize.org/prizes/physics/2024/popular-information/. 69 | 70 | We will use LLPhant to do the following steps: 71 | - read the PDF file; 72 | - extract the text from the PDF; 73 | - split the document in chunk of 800 characters; 74 | - generate the embeddings using Llama 3.2 model; 75 | - store the embeddings in Elasticsearch; 76 | 77 | When we will have the chunks stored in Elasticsearch we can implement the RAG architecture using the 78 | [Question Answering feature](https://github.com/theodo-group/LLPhant?tab=readme-ov-file#question-answering) of LLPhant. 79 | 80 | The embeddings is provided using the `src/embedding.php` and the question answering is implemented in `src/qa.php`. 81 | You need to execute the `embedding` first and the `qa` after, as follows: 82 | 83 | ```bash 84 | php src/embedding.php 85 | php src/qa.php 86 | ``` 87 | 88 | The output of `src/qa.php` will be something as follows: 89 | 90 | ``` 91 | -- Answer: 92 | The winners of the Nobel Prize in Physics for 2024 are John J. Hopfield and Geoffrey Hinton. 93 | 94 | We used 4 documents to answer the question, as follows: 95 | 96 | -- Document: ./data/nobel_prize_physics_2024.pdf 97 | -- Hash: 899fd14b31a9c2989ec584ff7fe766bbb6907378fd14083f5f6933fcb7ec75f1 98 | -- Content of 485 characters, extract: Professor at University of Toronto, Canada 99 | ... 100 | ``` 101 | 102 | We expanded the knowledge of Llama 3.2, now it knows who won the Nobel Prize in Physics 2024! 103 | 104 | # Copyright 105 | 106 | Copyright by [Enrico Zimuel](https://www.zimuel.it/), 2024. -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "php": "^8.1", 4 | "theodo-group/llphant": "^0.8.12", 5 | "elasticsearch/elasticsearch": "^8.16" 6 | }, 7 | "config": { 8 | "allow-plugins": { 9 | "php-http/discovery": true 10 | } 11 | }, 12 | "autoload": { 13 | "files": [ "./src/utility.php" ] 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "1fb213187fca9662717f3f10342c27da", 8 | "packages": [ 9 | { 10 | "name": "elastic/transport", 11 | "version": "v8.10.0", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/elastic/elastic-transport-php.git", 15 | "reference": "8be37d679637545e50b1cea9f8ee903888783021" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/elastic/elastic-transport-php/zipball/8be37d679637545e50b1cea9f8ee903888783021", 20 | "reference": "8be37d679637545e50b1cea9f8ee903888783021", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "composer-runtime-api": "^2.0", 25 | "open-telemetry/api": "^1.0", 26 | "php": "^7.4 || ^8.0", 27 | "php-http/discovery": "^1.14", 28 | "php-http/httplug": "^2.3", 29 | "psr/http-client": "^1.0", 30 | "psr/http-factory": "^1.0", 31 | "psr/http-message": "^1.0 || ^2.0", 32 | "psr/log": "^1 || ^2 || ^3" 33 | }, 34 | "require-dev": { 35 | "nyholm/psr7": "^1.5", 36 | "open-telemetry/sdk": "^1.0", 37 | "php-http/mock-client": "^1.5", 38 | "phpstan/phpstan": "^1.4", 39 | "phpunit/phpunit": "^9.5", 40 | "symfony/http-client": "^5.4" 41 | }, 42 | "type": "library", 43 | "autoload": { 44 | "psr-4": { 45 | "Elastic\\Transport\\": "src/" 46 | } 47 | }, 48 | "notification-url": "https://packagist.org/downloads/", 49 | "license": [ 50 | "MIT" 51 | ], 52 | "description": "HTTP transport PHP library for Elastic products", 53 | "keywords": [ 54 | "PSR_17", 55 | "elastic", 56 | "http", 57 | "psr-18", 58 | "psr-7", 59 | "transport" 60 | ], 61 | "support": { 62 | "issues": "https://github.com/elastic/elastic-transport-php/issues", 63 | "source": "https://github.com/elastic/elastic-transport-php/tree/v8.10.0" 64 | }, 65 | "time": "2024-08-14T08:55:07+00:00" 66 | }, 67 | { 68 | "name": "elasticsearch/elasticsearch", 69 | "version": "v8.16.0", 70 | "source": { 71 | "type": "git", 72 | "url": "https://github.com/elastic/elasticsearch-php.git", 73 | "reference": "ab0fdb43f9e69f0d0539028d8b0b56cdf3328d85" 74 | }, 75 | "dist": { 76 | "type": "zip", 77 | "url": "https://api.github.com/repos/elastic/elasticsearch-php/zipball/ab0fdb43f9e69f0d0539028d8b0b56cdf3328d85", 78 | "reference": "ab0fdb43f9e69f0d0539028d8b0b56cdf3328d85", 79 | "shasum": "" 80 | }, 81 | "require": { 82 | "elastic/transport": "^8.10", 83 | "guzzlehttp/guzzle": "^7.0", 84 | "php": "^7.4 || ^8.0", 85 | "psr/http-client": "^1.0", 86 | "psr/http-message": "^1.1 || ^2.0", 87 | "psr/log": "^1|^2|^3" 88 | }, 89 | "require-dev": { 90 | "ext-yaml": "*", 91 | "ext-zip": "*", 92 | "mockery/mockery": "^1.5", 93 | "nyholm/psr7": "^1.5", 94 | "php-http/message-factory": "^1.0", 95 | "php-http/mock-client": "^1.5", 96 | "phpstan/phpstan": "^1.4", 97 | "phpunit/phpunit": "^9.5", 98 | "psr/http-factory": "^1.0", 99 | "symfony/finder": "~4.0", 100 | "symfony/http-client": "^5.0|^6.0|^7.0" 101 | }, 102 | "type": "library", 103 | "autoload": { 104 | "psr-4": { 105 | "Elastic\\Elasticsearch\\": "src/" 106 | } 107 | }, 108 | "notification-url": "https://packagist.org/downloads/", 109 | "license": [ 110 | "MIT" 111 | ], 112 | "description": "PHP Client for Elasticsearch", 113 | "keywords": [ 114 | "client", 115 | "elastic", 116 | "elasticsearch", 117 | "search" 118 | ], 119 | "support": { 120 | "issues": "https://github.com/elastic/elasticsearch-php/issues", 121 | "source": "https://github.com/elastic/elasticsearch-php/tree/v8.16.0" 122 | }, 123 | "time": "2024-11-14T22:23:33+00:00" 124 | }, 125 | { 126 | "name": "guzzlehttp/guzzle", 127 | "version": "7.9.2", 128 | "source": { 129 | "type": "git", 130 | "url": "https://github.com/guzzle/guzzle.git", 131 | "reference": "d281ed313b989f213357e3be1a179f02196ac99b" 132 | }, 133 | "dist": { 134 | "type": "zip", 135 | "url": "https://api.github.com/repos/guzzle/guzzle/zipball/d281ed313b989f213357e3be1a179f02196ac99b", 136 | "reference": "d281ed313b989f213357e3be1a179f02196ac99b", 137 | "shasum": "" 138 | }, 139 | "require": { 140 | "ext-json": "*", 141 | "guzzlehttp/promises": "^1.5.3 || ^2.0.3", 142 | "guzzlehttp/psr7": "^2.7.0", 143 | "php": "^7.2.5 || ^8.0", 144 | "psr/http-client": "^1.0", 145 | "symfony/deprecation-contracts": "^2.2 || ^3.0" 146 | }, 147 | "provide": { 148 | "psr/http-client-implementation": "1.0" 149 | }, 150 | "require-dev": { 151 | "bamarni/composer-bin-plugin": "^1.8.2", 152 | "ext-curl": "*", 153 | "guzzle/client-integration-tests": "3.0.2", 154 | "php-http/message-factory": "^1.1", 155 | "phpunit/phpunit": "^8.5.39 || ^9.6.20", 156 | "psr/log": "^1.1 || ^2.0 || ^3.0" 157 | }, 158 | "suggest": { 159 | "ext-curl": "Required for CURL handler support", 160 | "ext-intl": "Required for Internationalized Domain Name (IDN) support", 161 | "psr/log": "Required for using the Log middleware" 162 | }, 163 | "type": "library", 164 | "extra": { 165 | "bamarni-bin": { 166 | "bin-links": true, 167 | "forward-command": false 168 | } 169 | }, 170 | "autoload": { 171 | "files": [ 172 | "src/functions_include.php" 173 | ], 174 | "psr-4": { 175 | "GuzzleHttp\\": "src/" 176 | } 177 | }, 178 | "notification-url": "https://packagist.org/downloads/", 179 | "license": [ 180 | "MIT" 181 | ], 182 | "authors": [ 183 | { 184 | "name": "Graham Campbell", 185 | "email": "hello@gjcampbell.co.uk", 186 | "homepage": "https://github.com/GrahamCampbell" 187 | }, 188 | { 189 | "name": "Michael Dowling", 190 | "email": "mtdowling@gmail.com", 191 | "homepage": "https://github.com/mtdowling" 192 | }, 193 | { 194 | "name": "Jeremy Lindblom", 195 | "email": "jeremeamia@gmail.com", 196 | "homepage": "https://github.com/jeremeamia" 197 | }, 198 | { 199 | "name": "George Mponos", 200 | "email": "gmponos@gmail.com", 201 | "homepage": "https://github.com/gmponos" 202 | }, 203 | { 204 | "name": "Tobias Nyholm", 205 | "email": "tobias.nyholm@gmail.com", 206 | "homepage": "https://github.com/Nyholm" 207 | }, 208 | { 209 | "name": "Márk Sági-Kazár", 210 | "email": "mark.sagikazar@gmail.com", 211 | "homepage": "https://github.com/sagikazarmark" 212 | }, 213 | { 214 | "name": "Tobias Schultze", 215 | "email": "webmaster@tubo-world.de", 216 | "homepage": "https://github.com/Tobion" 217 | } 218 | ], 219 | "description": "Guzzle is a PHP HTTP client library", 220 | "keywords": [ 221 | "client", 222 | "curl", 223 | "framework", 224 | "http", 225 | "http client", 226 | "psr-18", 227 | "psr-7", 228 | "rest", 229 | "web service" 230 | ], 231 | "support": { 232 | "issues": "https://github.com/guzzle/guzzle/issues", 233 | "source": "https://github.com/guzzle/guzzle/tree/7.9.2" 234 | }, 235 | "funding": [ 236 | { 237 | "url": "https://github.com/GrahamCampbell", 238 | "type": "github" 239 | }, 240 | { 241 | "url": "https://github.com/Nyholm", 242 | "type": "github" 243 | }, 244 | { 245 | "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", 246 | "type": "tidelift" 247 | } 248 | ], 249 | "time": "2024-07-24T11:22:20+00:00" 250 | }, 251 | { 252 | "name": "guzzlehttp/promises", 253 | "version": "2.0.4", 254 | "source": { 255 | "type": "git", 256 | "url": "https://github.com/guzzle/promises.git", 257 | "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455" 258 | }, 259 | "dist": { 260 | "type": "zip", 261 | "url": "https://api.github.com/repos/guzzle/promises/zipball/f9c436286ab2892c7db7be8c8da4ef61ccf7b455", 262 | "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455", 263 | "shasum": "" 264 | }, 265 | "require": { 266 | "php": "^7.2.5 || ^8.0" 267 | }, 268 | "require-dev": { 269 | "bamarni/composer-bin-plugin": "^1.8.2", 270 | "phpunit/phpunit": "^8.5.39 || ^9.6.20" 271 | }, 272 | "type": "library", 273 | "extra": { 274 | "bamarni-bin": { 275 | "bin-links": true, 276 | "forward-command": false 277 | } 278 | }, 279 | "autoload": { 280 | "psr-4": { 281 | "GuzzleHttp\\Promise\\": "src/" 282 | } 283 | }, 284 | "notification-url": "https://packagist.org/downloads/", 285 | "license": [ 286 | "MIT" 287 | ], 288 | "authors": [ 289 | { 290 | "name": "Graham Campbell", 291 | "email": "hello@gjcampbell.co.uk", 292 | "homepage": "https://github.com/GrahamCampbell" 293 | }, 294 | { 295 | "name": "Michael Dowling", 296 | "email": "mtdowling@gmail.com", 297 | "homepage": "https://github.com/mtdowling" 298 | }, 299 | { 300 | "name": "Tobias Nyholm", 301 | "email": "tobias.nyholm@gmail.com", 302 | "homepage": "https://github.com/Nyholm" 303 | }, 304 | { 305 | "name": "Tobias Schultze", 306 | "email": "webmaster@tubo-world.de", 307 | "homepage": "https://github.com/Tobion" 308 | } 309 | ], 310 | "description": "Guzzle promises library", 311 | "keywords": [ 312 | "promise" 313 | ], 314 | "support": { 315 | "issues": "https://github.com/guzzle/promises/issues", 316 | "source": "https://github.com/guzzle/promises/tree/2.0.4" 317 | }, 318 | "funding": [ 319 | { 320 | "url": "https://github.com/GrahamCampbell", 321 | "type": "github" 322 | }, 323 | { 324 | "url": "https://github.com/Nyholm", 325 | "type": "github" 326 | }, 327 | { 328 | "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", 329 | "type": "tidelift" 330 | } 331 | ], 332 | "time": "2024-10-17T10:06:22+00:00" 333 | }, 334 | { 335 | "name": "guzzlehttp/psr7", 336 | "version": "2.7.0", 337 | "source": { 338 | "type": "git", 339 | "url": "https://github.com/guzzle/psr7.git", 340 | "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201" 341 | }, 342 | "dist": { 343 | "type": "zip", 344 | "url": "https://api.github.com/repos/guzzle/psr7/zipball/a70f5c95fb43bc83f07c9c948baa0dc1829bf201", 345 | "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201", 346 | "shasum": "" 347 | }, 348 | "require": { 349 | "php": "^7.2.5 || ^8.0", 350 | "psr/http-factory": "^1.0", 351 | "psr/http-message": "^1.1 || ^2.0", 352 | "ralouphie/getallheaders": "^3.0" 353 | }, 354 | "provide": { 355 | "psr/http-factory-implementation": "1.0", 356 | "psr/http-message-implementation": "1.0" 357 | }, 358 | "require-dev": { 359 | "bamarni/composer-bin-plugin": "^1.8.2", 360 | "http-interop/http-factory-tests": "0.9.0", 361 | "phpunit/phpunit": "^8.5.39 || ^9.6.20" 362 | }, 363 | "suggest": { 364 | "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" 365 | }, 366 | "type": "library", 367 | "extra": { 368 | "bamarni-bin": { 369 | "bin-links": true, 370 | "forward-command": false 371 | } 372 | }, 373 | "autoload": { 374 | "psr-4": { 375 | "GuzzleHttp\\Psr7\\": "src/" 376 | } 377 | }, 378 | "notification-url": "https://packagist.org/downloads/", 379 | "license": [ 380 | "MIT" 381 | ], 382 | "authors": [ 383 | { 384 | "name": "Graham Campbell", 385 | "email": "hello@gjcampbell.co.uk", 386 | "homepage": "https://github.com/GrahamCampbell" 387 | }, 388 | { 389 | "name": "Michael Dowling", 390 | "email": "mtdowling@gmail.com", 391 | "homepage": "https://github.com/mtdowling" 392 | }, 393 | { 394 | "name": "George Mponos", 395 | "email": "gmponos@gmail.com", 396 | "homepage": "https://github.com/gmponos" 397 | }, 398 | { 399 | "name": "Tobias Nyholm", 400 | "email": "tobias.nyholm@gmail.com", 401 | "homepage": "https://github.com/Nyholm" 402 | }, 403 | { 404 | "name": "Márk Sági-Kazár", 405 | "email": "mark.sagikazar@gmail.com", 406 | "homepage": "https://github.com/sagikazarmark" 407 | }, 408 | { 409 | "name": "Tobias Schultze", 410 | "email": "webmaster@tubo-world.de", 411 | "homepage": "https://github.com/Tobion" 412 | }, 413 | { 414 | "name": "Márk Sági-Kazár", 415 | "email": "mark.sagikazar@gmail.com", 416 | "homepage": "https://sagikazarmark.hu" 417 | } 418 | ], 419 | "description": "PSR-7 message implementation that also provides common utility methods", 420 | "keywords": [ 421 | "http", 422 | "message", 423 | "psr-7", 424 | "request", 425 | "response", 426 | "stream", 427 | "uri", 428 | "url" 429 | ], 430 | "support": { 431 | "issues": "https://github.com/guzzle/psr7/issues", 432 | "source": "https://github.com/guzzle/psr7/tree/2.7.0" 433 | }, 434 | "funding": [ 435 | { 436 | "url": "https://github.com/GrahamCampbell", 437 | "type": "github" 438 | }, 439 | { 440 | "url": "https://github.com/Nyholm", 441 | "type": "github" 442 | }, 443 | { 444 | "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", 445 | "type": "tidelift" 446 | } 447 | ], 448 | "time": "2024-07-18T11:15:46+00:00" 449 | }, 450 | { 451 | "name": "open-telemetry/api", 452 | "version": "1.1.1", 453 | "source": { 454 | "type": "git", 455 | "url": "https://github.com/opentelemetry-php/api.git", 456 | "reference": "542064815d38a6df55af7957cd6f1d7d967c99c6" 457 | }, 458 | "dist": { 459 | "type": "zip", 460 | "url": "https://api.github.com/repos/opentelemetry-php/api/zipball/542064815d38a6df55af7957cd6f1d7d967c99c6", 461 | "reference": "542064815d38a6df55af7957cd6f1d7d967c99c6", 462 | "shasum": "" 463 | }, 464 | "require": { 465 | "open-telemetry/context": "^1.0", 466 | "php": "^8.1", 467 | "psr/log": "^1.1|^2.0|^3.0", 468 | "symfony/polyfill-php82": "^1.26" 469 | }, 470 | "conflict": { 471 | "open-telemetry/sdk": "<=1.0.8" 472 | }, 473 | "type": "library", 474 | "extra": { 475 | "branch-alias": { 476 | "dev-main": "1.1.x-dev" 477 | }, 478 | "spi": { 479 | "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\HookManagerInterface": [ 480 | "OpenTelemetry\\API\\Instrumentation\\AutoInstrumentation\\ExtensionHookManager" 481 | ] 482 | } 483 | }, 484 | "autoload": { 485 | "files": [ 486 | "Trace/functions.php" 487 | ], 488 | "psr-4": { 489 | "OpenTelemetry\\API\\": "." 490 | } 491 | }, 492 | "notification-url": "https://packagist.org/downloads/", 493 | "license": [ 494 | "Apache-2.0" 495 | ], 496 | "authors": [ 497 | { 498 | "name": "opentelemetry-php contributors", 499 | "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" 500 | } 501 | ], 502 | "description": "API for OpenTelemetry PHP.", 503 | "keywords": [ 504 | "Metrics", 505 | "api", 506 | "apm", 507 | "logging", 508 | "opentelemetry", 509 | "otel", 510 | "tracing" 511 | ], 512 | "support": { 513 | "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", 514 | "docs": "https://opentelemetry.io/docs/php", 515 | "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", 516 | "source": "https://github.com/open-telemetry/opentelemetry-php" 517 | }, 518 | "time": "2024-10-15T22:42:37+00:00" 519 | }, 520 | { 521 | "name": "open-telemetry/context", 522 | "version": "1.1.0", 523 | "source": { 524 | "type": "git", 525 | "url": "https://github.com/opentelemetry-php/context.git", 526 | "reference": "0cba875ea1953435f78aec7f1d75afa87bdbf7f3" 527 | }, 528 | "dist": { 529 | "type": "zip", 530 | "url": "https://api.github.com/repos/opentelemetry-php/context/zipball/0cba875ea1953435f78aec7f1d75afa87bdbf7f3", 531 | "reference": "0cba875ea1953435f78aec7f1d75afa87bdbf7f3", 532 | "shasum": "" 533 | }, 534 | "require": { 535 | "php": "^8.1", 536 | "symfony/polyfill-php82": "^1.26" 537 | }, 538 | "suggest": { 539 | "ext-ffi": "To allow context switching in Fibers" 540 | }, 541 | "type": "library", 542 | "extra": { 543 | "branch-alias": { 544 | "dev-main": "1.0.x-dev" 545 | } 546 | }, 547 | "autoload": { 548 | "files": [ 549 | "fiber/initialize_fiber_handler.php" 550 | ], 551 | "psr-4": { 552 | "OpenTelemetry\\Context\\": "." 553 | } 554 | }, 555 | "notification-url": "https://packagist.org/downloads/", 556 | "license": [ 557 | "Apache-2.0" 558 | ], 559 | "authors": [ 560 | { 561 | "name": "opentelemetry-php contributors", 562 | "homepage": "https://github.com/open-telemetry/opentelemetry-php/graphs/contributors" 563 | } 564 | ], 565 | "description": "Context implementation for OpenTelemetry PHP.", 566 | "keywords": [ 567 | "Context", 568 | "opentelemetry", 569 | "otel" 570 | ], 571 | "support": { 572 | "chat": "https://app.slack.com/client/T08PSQ7BQ/C01NFPCV44V", 573 | "docs": "https://opentelemetry.io/docs/php", 574 | "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", 575 | "source": "https://github.com/open-telemetry/opentelemetry-php" 576 | }, 577 | "time": "2024-08-21T00:29:20+00:00" 578 | }, 579 | { 580 | "name": "openai-php/client", 581 | "version": "v0.10.3", 582 | "source": { 583 | "type": "git", 584 | "url": "https://github.com/openai-php/client.git", 585 | "reference": "4a565d145e0fb3ea1baba8fffe39d86c56b6dc2c" 586 | }, 587 | "dist": { 588 | "type": "zip", 589 | "url": "https://api.github.com/repos/openai-php/client/zipball/4a565d145e0fb3ea1baba8fffe39d86c56b6dc2c", 590 | "reference": "4a565d145e0fb3ea1baba8fffe39d86c56b6dc2c", 591 | "shasum": "" 592 | }, 593 | "require": { 594 | "php": "^8.1.0", 595 | "php-http/discovery": "^1.20.0", 596 | "php-http/multipart-stream-builder": "^1.4.2", 597 | "psr/http-client": "^1.0.3", 598 | "psr/http-client-implementation": "^1.0.1", 599 | "psr/http-factory-implementation": "*", 600 | "psr/http-message": "^1.1.0|^2.0.0" 601 | }, 602 | "require-dev": { 603 | "guzzlehttp/guzzle": "^7.9.2", 604 | "guzzlehttp/psr7": "^2.7.0", 605 | "laravel/pint": "^1.18.1", 606 | "mockery/mockery": "^1.6.12", 607 | "nunomaduro/collision": "^7.11.0|^8.5.0", 608 | "pestphp/pest": "^2.36.0|^3.5.0", 609 | "pestphp/pest-plugin-arch": "^2.7|^3.0", 610 | "pestphp/pest-plugin-type-coverage": "^2.8.7|^3.1.0", 611 | "phpstan/phpstan": "^1.12.7", 612 | "symfony/var-dumper": "^6.4.11|^7.1.5" 613 | }, 614 | "type": "library", 615 | "autoload": { 616 | "files": [ 617 | "src/OpenAI.php" 618 | ], 619 | "psr-4": { 620 | "OpenAI\\": "src/" 621 | } 622 | }, 623 | "notification-url": "https://packagist.org/downloads/", 624 | "license": [ 625 | "MIT" 626 | ], 627 | "authors": [ 628 | { 629 | "name": "Nuno Maduro", 630 | "email": "enunomaduro@gmail.com" 631 | }, 632 | { 633 | "name": "Sandro Gehri" 634 | } 635 | ], 636 | "description": "OpenAI PHP is a supercharged PHP API client that allows you to interact with the Open AI API", 637 | "keywords": [ 638 | "GPT-3", 639 | "api", 640 | "client", 641 | "codex", 642 | "dall-e", 643 | "language", 644 | "natural", 645 | "openai", 646 | "php", 647 | "processing", 648 | "sdk" 649 | ], 650 | "support": { 651 | "issues": "https://github.com/openai-php/client/issues", 652 | "source": "https://github.com/openai-php/client/tree/v0.10.3" 653 | }, 654 | "funding": [ 655 | { 656 | "url": "https://www.paypal.com/paypalme/enunomaduro", 657 | "type": "custom" 658 | }, 659 | { 660 | "url": "https://github.com/gehrisandro", 661 | "type": "github" 662 | }, 663 | { 664 | "url": "https://github.com/nunomaduro", 665 | "type": "github" 666 | } 667 | ], 668 | "time": "2024-11-12T20:51:16+00:00" 669 | }, 670 | { 671 | "name": "php-http/discovery", 672 | "version": "1.20.0", 673 | "source": { 674 | "type": "git", 675 | "url": "https://github.com/php-http/discovery.git", 676 | "reference": "82fe4c73ef3363caed49ff8dd1539ba06044910d" 677 | }, 678 | "dist": { 679 | "type": "zip", 680 | "url": "https://api.github.com/repos/php-http/discovery/zipball/82fe4c73ef3363caed49ff8dd1539ba06044910d", 681 | "reference": "82fe4c73ef3363caed49ff8dd1539ba06044910d", 682 | "shasum": "" 683 | }, 684 | "require": { 685 | "composer-plugin-api": "^1.0|^2.0", 686 | "php": "^7.1 || ^8.0" 687 | }, 688 | "conflict": { 689 | "nyholm/psr7": "<1.0", 690 | "zendframework/zend-diactoros": "*" 691 | }, 692 | "provide": { 693 | "php-http/async-client-implementation": "*", 694 | "php-http/client-implementation": "*", 695 | "psr/http-client-implementation": "*", 696 | "psr/http-factory-implementation": "*", 697 | "psr/http-message-implementation": "*" 698 | }, 699 | "require-dev": { 700 | "composer/composer": "^1.0.2|^2.0", 701 | "graham-campbell/phpspec-skip-example-extension": "^5.0", 702 | "php-http/httplug": "^1.0 || ^2.0", 703 | "php-http/message-factory": "^1.0", 704 | "phpspec/phpspec": "^5.1 || ^6.1 || ^7.3", 705 | "sebastian/comparator": "^3.0.5 || ^4.0.8", 706 | "symfony/phpunit-bridge": "^6.4.4 || ^7.0.1" 707 | }, 708 | "type": "composer-plugin", 709 | "extra": { 710 | "class": "Http\\Discovery\\Composer\\Plugin", 711 | "plugin-optional": true 712 | }, 713 | "autoload": { 714 | "psr-4": { 715 | "Http\\Discovery\\": "src/" 716 | }, 717 | "exclude-from-classmap": [ 718 | "src/Composer/Plugin.php" 719 | ] 720 | }, 721 | "notification-url": "https://packagist.org/downloads/", 722 | "license": [ 723 | "MIT" 724 | ], 725 | "authors": [ 726 | { 727 | "name": "Márk Sági-Kazár", 728 | "email": "mark.sagikazar@gmail.com" 729 | } 730 | ], 731 | "description": "Finds and installs PSR-7, PSR-17, PSR-18 and HTTPlug implementations", 732 | "homepage": "http://php-http.org", 733 | "keywords": [ 734 | "adapter", 735 | "client", 736 | "discovery", 737 | "factory", 738 | "http", 739 | "message", 740 | "psr17", 741 | "psr7" 742 | ], 743 | "support": { 744 | "issues": "https://github.com/php-http/discovery/issues", 745 | "source": "https://github.com/php-http/discovery/tree/1.20.0" 746 | }, 747 | "time": "2024-10-02T11:20:13+00:00" 748 | }, 749 | { 750 | "name": "php-http/httplug", 751 | "version": "2.4.1", 752 | "source": { 753 | "type": "git", 754 | "url": "https://github.com/php-http/httplug.git", 755 | "reference": "5cad731844891a4c282f3f3e1b582c46839d22f4" 756 | }, 757 | "dist": { 758 | "type": "zip", 759 | "url": "https://api.github.com/repos/php-http/httplug/zipball/5cad731844891a4c282f3f3e1b582c46839d22f4", 760 | "reference": "5cad731844891a4c282f3f3e1b582c46839d22f4", 761 | "shasum": "" 762 | }, 763 | "require": { 764 | "php": "^7.1 || ^8.0", 765 | "php-http/promise": "^1.1", 766 | "psr/http-client": "^1.0", 767 | "psr/http-message": "^1.0 || ^2.0" 768 | }, 769 | "require-dev": { 770 | "friends-of-phpspec/phpspec-code-coverage": "^4.1 || ^5.0 || ^6.0", 771 | "phpspec/phpspec": "^5.1 || ^6.0 || ^7.0" 772 | }, 773 | "type": "library", 774 | "autoload": { 775 | "psr-4": { 776 | "Http\\Client\\": "src/" 777 | } 778 | }, 779 | "notification-url": "https://packagist.org/downloads/", 780 | "license": [ 781 | "MIT" 782 | ], 783 | "authors": [ 784 | { 785 | "name": "Eric GELOEN", 786 | "email": "geloen.eric@gmail.com" 787 | }, 788 | { 789 | "name": "Márk Sági-Kazár", 790 | "email": "mark.sagikazar@gmail.com", 791 | "homepage": "https://sagikazarmark.hu" 792 | } 793 | ], 794 | "description": "HTTPlug, the HTTP client abstraction for PHP", 795 | "homepage": "http://httplug.io", 796 | "keywords": [ 797 | "client", 798 | "http" 799 | ], 800 | "support": { 801 | "issues": "https://github.com/php-http/httplug/issues", 802 | "source": "https://github.com/php-http/httplug/tree/2.4.1" 803 | }, 804 | "time": "2024-09-23T11:39:58+00:00" 805 | }, 806 | { 807 | "name": "php-http/multipart-stream-builder", 808 | "version": "1.4.2", 809 | "source": { 810 | "type": "git", 811 | "url": "https://github.com/php-http/multipart-stream-builder.git", 812 | "reference": "10086e6de6f53489cca5ecc45b6f468604d3460e" 813 | }, 814 | "dist": { 815 | "type": "zip", 816 | "url": "https://api.github.com/repos/php-http/multipart-stream-builder/zipball/10086e6de6f53489cca5ecc45b6f468604d3460e", 817 | "reference": "10086e6de6f53489cca5ecc45b6f468604d3460e", 818 | "shasum": "" 819 | }, 820 | "require": { 821 | "php": "^7.1 || ^8.0", 822 | "php-http/discovery": "^1.15", 823 | "psr/http-factory-implementation": "^1.0" 824 | }, 825 | "require-dev": { 826 | "nyholm/psr7": "^1.0", 827 | "php-http/message": "^1.5", 828 | "php-http/message-factory": "^1.0.2", 829 | "phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.3" 830 | }, 831 | "type": "library", 832 | "autoload": { 833 | "psr-4": { 834 | "Http\\Message\\MultipartStream\\": "src/" 835 | } 836 | }, 837 | "notification-url": "https://packagist.org/downloads/", 838 | "license": [ 839 | "MIT" 840 | ], 841 | "authors": [ 842 | { 843 | "name": "Tobias Nyholm", 844 | "email": "tobias.nyholm@gmail.com" 845 | } 846 | ], 847 | "description": "A builder class that help you create a multipart stream", 848 | "homepage": "http://php-http.org", 849 | "keywords": [ 850 | "factory", 851 | "http", 852 | "message", 853 | "multipart stream", 854 | "stream" 855 | ], 856 | "support": { 857 | "issues": "https://github.com/php-http/multipart-stream-builder/issues", 858 | "source": "https://github.com/php-http/multipart-stream-builder/tree/1.4.2" 859 | }, 860 | "time": "2024-09-04T13:22:54+00:00" 861 | }, 862 | { 863 | "name": "php-http/promise", 864 | "version": "1.3.1", 865 | "source": { 866 | "type": "git", 867 | "url": "https://github.com/php-http/promise.git", 868 | "reference": "fc85b1fba37c169a69a07ef0d5a8075770cc1f83" 869 | }, 870 | "dist": { 871 | "type": "zip", 872 | "url": "https://api.github.com/repos/php-http/promise/zipball/fc85b1fba37c169a69a07ef0d5a8075770cc1f83", 873 | "reference": "fc85b1fba37c169a69a07ef0d5a8075770cc1f83", 874 | "shasum": "" 875 | }, 876 | "require": { 877 | "php": "^7.1 || ^8.0" 878 | }, 879 | "require-dev": { 880 | "friends-of-phpspec/phpspec-code-coverage": "^4.3.2 || ^6.3", 881 | "phpspec/phpspec": "^5.1.2 || ^6.2 || ^7.4" 882 | }, 883 | "type": "library", 884 | "autoload": { 885 | "psr-4": { 886 | "Http\\Promise\\": "src/" 887 | } 888 | }, 889 | "notification-url": "https://packagist.org/downloads/", 890 | "license": [ 891 | "MIT" 892 | ], 893 | "authors": [ 894 | { 895 | "name": "Joel Wurtz", 896 | "email": "joel.wurtz@gmail.com" 897 | }, 898 | { 899 | "name": "Márk Sági-Kazár", 900 | "email": "mark.sagikazar@gmail.com" 901 | } 902 | ], 903 | "description": "Promise used for asynchronous HTTP requests", 904 | "homepage": "http://httplug.io", 905 | "keywords": [ 906 | "promise" 907 | ], 908 | "support": { 909 | "issues": "https://github.com/php-http/promise/issues", 910 | "source": "https://github.com/php-http/promise/tree/1.3.1" 911 | }, 912 | "time": "2024-03-15T13:55:21+00:00" 913 | }, 914 | { 915 | "name": "phpoffice/math", 916 | "version": "0.2.0", 917 | "source": { 918 | "type": "git", 919 | "url": "https://github.com/PHPOffice/Math.git", 920 | "reference": "fc2eb6d1a61b058d5dac77197059db30ee3c8329" 921 | }, 922 | "dist": { 923 | "type": "zip", 924 | "url": "https://api.github.com/repos/PHPOffice/Math/zipball/fc2eb6d1a61b058d5dac77197059db30ee3c8329", 925 | "reference": "fc2eb6d1a61b058d5dac77197059db30ee3c8329", 926 | "shasum": "" 927 | }, 928 | "require": { 929 | "ext-dom": "*", 930 | "ext-xml": "*", 931 | "php": "^7.1|^8.0" 932 | }, 933 | "require-dev": { 934 | "phpstan/phpstan": "^0.12.88 || ^1.0.0", 935 | "phpunit/phpunit": "^7.0 || ^9.0" 936 | }, 937 | "type": "library", 938 | "autoload": { 939 | "psr-4": { 940 | "PhpOffice\\Math\\": "src/Math/" 941 | } 942 | }, 943 | "notification-url": "https://packagist.org/downloads/", 944 | "license": [ 945 | "MIT" 946 | ], 947 | "authors": [ 948 | { 949 | "name": "Progi1984", 950 | "homepage": "https://lefevre.dev" 951 | } 952 | ], 953 | "description": "Math - Manipulate Math Formula", 954 | "homepage": "https://phpoffice.github.io/Math/", 955 | "keywords": [ 956 | "MathML", 957 | "officemathml", 958 | "php" 959 | ], 960 | "support": { 961 | "issues": "https://github.com/PHPOffice/Math/issues", 962 | "source": "https://github.com/PHPOffice/Math/tree/0.2.0" 963 | }, 964 | "time": "2024-08-12T07:30:45+00:00" 965 | }, 966 | { 967 | "name": "phpoffice/phpword", 968 | "version": "1.3.0", 969 | "source": { 970 | "type": "git", 971 | "url": "https://github.com/PHPOffice/PHPWord.git", 972 | "reference": "8392134ce4b5dba65130ba956231a1602b848b7f" 973 | }, 974 | "dist": { 975 | "type": "zip", 976 | "url": "https://api.github.com/repos/PHPOffice/PHPWord/zipball/8392134ce4b5dba65130ba956231a1602b848b7f", 977 | "reference": "8392134ce4b5dba65130ba956231a1602b848b7f", 978 | "shasum": "" 979 | }, 980 | "require": { 981 | "ext-dom": "*", 982 | "ext-json": "*", 983 | "ext-xml": "*", 984 | "php": "^7.1|^8.0", 985 | "phpoffice/math": "^0.2" 986 | }, 987 | "require-dev": { 988 | "dompdf/dompdf": "^2.0", 989 | "ext-gd": "*", 990 | "ext-libxml": "*", 991 | "ext-zip": "*", 992 | "friendsofphp/php-cs-fixer": "^3.3", 993 | "mpdf/mpdf": "^8.1", 994 | "phpmd/phpmd": "^2.13", 995 | "phpstan/phpstan-phpunit": "@stable", 996 | "phpunit/phpunit": ">=7.0", 997 | "symfony/process": "^4.4 || ^5.0", 998 | "tecnickcom/tcpdf": "^6.5" 999 | }, 1000 | "suggest": { 1001 | "dompdf/dompdf": "Allows writing PDF", 1002 | "ext-gd2": "Allows adding images", 1003 | "ext-xmlwriter": "Allows writing OOXML and ODF", 1004 | "ext-xsl": "Allows applying XSL style sheet to headers, to main document part, and to footers of an OOXML template", 1005 | "ext-zip": "Allows writing OOXML and ODF" 1006 | }, 1007 | "type": "library", 1008 | "autoload": { 1009 | "psr-4": { 1010 | "PhpOffice\\PhpWord\\": "src/PhpWord" 1011 | } 1012 | }, 1013 | "notification-url": "https://packagist.org/downloads/", 1014 | "license": [ 1015 | "LGPL-3.0" 1016 | ], 1017 | "authors": [ 1018 | { 1019 | "name": "Mark Baker" 1020 | }, 1021 | { 1022 | "name": "Gabriel Bull", 1023 | "email": "me@gabrielbull.com", 1024 | "homepage": "http://gabrielbull.com/" 1025 | }, 1026 | { 1027 | "name": "Franck Lefevre", 1028 | "homepage": "https://rootslabs.net/blog/" 1029 | }, 1030 | { 1031 | "name": "Ivan Lanin", 1032 | "homepage": "http://ivan.lanin.org" 1033 | }, 1034 | { 1035 | "name": "Roman Syroeshko", 1036 | "homepage": "http://ru.linkedin.com/pub/roman-syroeshko/34/a53/994/" 1037 | }, 1038 | { 1039 | "name": "Antoine de Troostembergh" 1040 | } 1041 | ], 1042 | "description": "PHPWord - A pure PHP library for reading and writing word processing documents (OOXML, ODF, RTF, HTML, PDF)", 1043 | "homepage": "https://phpoffice.github.io/PHPWord/", 1044 | "keywords": [ 1045 | "ISO IEC 29500", 1046 | "OOXML", 1047 | "Office Open XML", 1048 | "OpenDocument", 1049 | "OpenXML", 1050 | "PhpOffice", 1051 | "PhpWord", 1052 | "Rich Text Format", 1053 | "WordprocessingML", 1054 | "doc", 1055 | "docx", 1056 | "html", 1057 | "odf", 1058 | "odt", 1059 | "office", 1060 | "pdf", 1061 | "php", 1062 | "reader", 1063 | "rtf", 1064 | "template", 1065 | "template processor", 1066 | "word", 1067 | "writer" 1068 | ], 1069 | "support": { 1070 | "issues": "https://github.com/PHPOffice/PHPWord/issues", 1071 | "source": "https://github.com/PHPOffice/PHPWord/tree/1.3.0" 1072 | }, 1073 | "time": "2024-08-30T18:03:42+00:00" 1074 | }, 1075 | { 1076 | "name": "psr/http-client", 1077 | "version": "1.0.3", 1078 | "source": { 1079 | "type": "git", 1080 | "url": "https://github.com/php-fig/http-client.git", 1081 | "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" 1082 | }, 1083 | "dist": { 1084 | "type": "zip", 1085 | "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", 1086 | "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", 1087 | "shasum": "" 1088 | }, 1089 | "require": { 1090 | "php": "^7.0 || ^8.0", 1091 | "psr/http-message": "^1.0 || ^2.0" 1092 | }, 1093 | "type": "library", 1094 | "extra": { 1095 | "branch-alias": { 1096 | "dev-master": "1.0.x-dev" 1097 | } 1098 | }, 1099 | "autoload": { 1100 | "psr-4": { 1101 | "Psr\\Http\\Client\\": "src/" 1102 | } 1103 | }, 1104 | "notification-url": "https://packagist.org/downloads/", 1105 | "license": [ 1106 | "MIT" 1107 | ], 1108 | "authors": [ 1109 | { 1110 | "name": "PHP-FIG", 1111 | "homepage": "https://www.php-fig.org/" 1112 | } 1113 | ], 1114 | "description": "Common interface for HTTP clients", 1115 | "homepage": "https://github.com/php-fig/http-client", 1116 | "keywords": [ 1117 | "http", 1118 | "http-client", 1119 | "psr", 1120 | "psr-18" 1121 | ], 1122 | "support": { 1123 | "source": "https://github.com/php-fig/http-client" 1124 | }, 1125 | "time": "2023-09-23T14:17:50+00:00" 1126 | }, 1127 | { 1128 | "name": "psr/http-factory", 1129 | "version": "1.1.0", 1130 | "source": { 1131 | "type": "git", 1132 | "url": "https://github.com/php-fig/http-factory.git", 1133 | "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" 1134 | }, 1135 | "dist": { 1136 | "type": "zip", 1137 | "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", 1138 | "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", 1139 | "shasum": "" 1140 | }, 1141 | "require": { 1142 | "php": ">=7.1", 1143 | "psr/http-message": "^1.0 || ^2.0" 1144 | }, 1145 | "type": "library", 1146 | "extra": { 1147 | "branch-alias": { 1148 | "dev-master": "1.0.x-dev" 1149 | } 1150 | }, 1151 | "autoload": { 1152 | "psr-4": { 1153 | "Psr\\Http\\Message\\": "src/" 1154 | } 1155 | }, 1156 | "notification-url": "https://packagist.org/downloads/", 1157 | "license": [ 1158 | "MIT" 1159 | ], 1160 | "authors": [ 1161 | { 1162 | "name": "PHP-FIG", 1163 | "homepage": "https://www.php-fig.org/" 1164 | } 1165 | ], 1166 | "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", 1167 | "keywords": [ 1168 | "factory", 1169 | "http", 1170 | "message", 1171 | "psr", 1172 | "psr-17", 1173 | "psr-7", 1174 | "request", 1175 | "response" 1176 | ], 1177 | "support": { 1178 | "source": "https://github.com/php-fig/http-factory" 1179 | }, 1180 | "time": "2024-04-15T12:06:14+00:00" 1181 | }, 1182 | { 1183 | "name": "psr/http-message", 1184 | "version": "2.0", 1185 | "source": { 1186 | "type": "git", 1187 | "url": "https://github.com/php-fig/http-message.git", 1188 | "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" 1189 | }, 1190 | "dist": { 1191 | "type": "zip", 1192 | "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", 1193 | "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", 1194 | "shasum": "" 1195 | }, 1196 | "require": { 1197 | "php": "^7.2 || ^8.0" 1198 | }, 1199 | "type": "library", 1200 | "extra": { 1201 | "branch-alias": { 1202 | "dev-master": "2.0.x-dev" 1203 | } 1204 | }, 1205 | "autoload": { 1206 | "psr-4": { 1207 | "Psr\\Http\\Message\\": "src/" 1208 | } 1209 | }, 1210 | "notification-url": "https://packagist.org/downloads/", 1211 | "license": [ 1212 | "MIT" 1213 | ], 1214 | "authors": [ 1215 | { 1216 | "name": "PHP-FIG", 1217 | "homepage": "https://www.php-fig.org/" 1218 | } 1219 | ], 1220 | "description": "Common interface for HTTP messages", 1221 | "homepage": "https://github.com/php-fig/http-message", 1222 | "keywords": [ 1223 | "http", 1224 | "http-message", 1225 | "psr", 1226 | "psr-7", 1227 | "request", 1228 | "response" 1229 | ], 1230 | "support": { 1231 | "source": "https://github.com/php-fig/http-message/tree/2.0" 1232 | }, 1233 | "time": "2023-04-04T09:54:51+00:00" 1234 | }, 1235 | { 1236 | "name": "psr/log", 1237 | "version": "3.0.2", 1238 | "source": { 1239 | "type": "git", 1240 | "url": "https://github.com/php-fig/log.git", 1241 | "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" 1242 | }, 1243 | "dist": { 1244 | "type": "zip", 1245 | "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", 1246 | "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", 1247 | "shasum": "" 1248 | }, 1249 | "require": { 1250 | "php": ">=8.0.0" 1251 | }, 1252 | "type": "library", 1253 | "extra": { 1254 | "branch-alias": { 1255 | "dev-master": "3.x-dev" 1256 | } 1257 | }, 1258 | "autoload": { 1259 | "psr-4": { 1260 | "Psr\\Log\\": "src" 1261 | } 1262 | }, 1263 | "notification-url": "https://packagist.org/downloads/", 1264 | "license": [ 1265 | "MIT" 1266 | ], 1267 | "authors": [ 1268 | { 1269 | "name": "PHP-FIG", 1270 | "homepage": "https://www.php-fig.org/" 1271 | } 1272 | ], 1273 | "description": "Common interface for logging libraries", 1274 | "homepage": "https://github.com/php-fig/log", 1275 | "keywords": [ 1276 | "log", 1277 | "psr", 1278 | "psr-3" 1279 | ], 1280 | "support": { 1281 | "source": "https://github.com/php-fig/log/tree/3.0.2" 1282 | }, 1283 | "time": "2024-09-11T13:17:53+00:00" 1284 | }, 1285 | { 1286 | "name": "ralouphie/getallheaders", 1287 | "version": "3.0.3", 1288 | "source": { 1289 | "type": "git", 1290 | "url": "https://github.com/ralouphie/getallheaders.git", 1291 | "reference": "120b605dfeb996808c31b6477290a714d356e822" 1292 | }, 1293 | "dist": { 1294 | "type": "zip", 1295 | "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", 1296 | "reference": "120b605dfeb996808c31b6477290a714d356e822", 1297 | "shasum": "" 1298 | }, 1299 | "require": { 1300 | "php": ">=5.6" 1301 | }, 1302 | "require-dev": { 1303 | "php-coveralls/php-coveralls": "^2.1", 1304 | "phpunit/phpunit": "^5 || ^6.5" 1305 | }, 1306 | "type": "library", 1307 | "autoload": { 1308 | "files": [ 1309 | "src/getallheaders.php" 1310 | ] 1311 | }, 1312 | "notification-url": "https://packagist.org/downloads/", 1313 | "license": [ 1314 | "MIT" 1315 | ], 1316 | "authors": [ 1317 | { 1318 | "name": "Ralph Khattar", 1319 | "email": "ralph.khattar@gmail.com" 1320 | } 1321 | ], 1322 | "description": "A polyfill for getallheaders.", 1323 | "support": { 1324 | "issues": "https://github.com/ralouphie/getallheaders/issues", 1325 | "source": "https://github.com/ralouphie/getallheaders/tree/develop" 1326 | }, 1327 | "time": "2019-03-08T08:55:37+00:00" 1328 | }, 1329 | { 1330 | "name": "smalot/pdfparser", 1331 | "version": "v2.11.0", 1332 | "source": { 1333 | "type": "git", 1334 | "url": "https://github.com/smalot/pdfparser.git", 1335 | "reference": "ac8e6678b0940e4b2ccd5caadd3fb18e68093be6" 1336 | }, 1337 | "dist": { 1338 | "type": "zip", 1339 | "url": "https://api.github.com/repos/smalot/pdfparser/zipball/ac8e6678b0940e4b2ccd5caadd3fb18e68093be6", 1340 | "reference": "ac8e6678b0940e4b2ccd5caadd3fb18e68093be6", 1341 | "shasum": "" 1342 | }, 1343 | "require": { 1344 | "ext-iconv": "*", 1345 | "ext-zlib": "*", 1346 | "php": ">=7.1", 1347 | "symfony/polyfill-mbstring": "^1.18" 1348 | }, 1349 | "type": "library", 1350 | "autoload": { 1351 | "psr-0": { 1352 | "Smalot\\PdfParser\\": "src/" 1353 | } 1354 | }, 1355 | "notification-url": "https://packagist.org/downloads/", 1356 | "license": [ 1357 | "LGPL-3.0" 1358 | ], 1359 | "authors": [ 1360 | { 1361 | "name": "Sebastien MALOT", 1362 | "email": "sebastien@malot.fr" 1363 | } 1364 | ], 1365 | "description": "Pdf parser library. Can read and extract information from pdf file.", 1366 | "homepage": "https://www.pdfparser.org", 1367 | "keywords": [ 1368 | "extract", 1369 | "parse", 1370 | "parser", 1371 | "pdf", 1372 | "text" 1373 | ], 1374 | "support": { 1375 | "issues": "https://github.com/smalot/pdfparser/issues", 1376 | "source": "https://github.com/smalot/pdfparser/tree/v2.11.0" 1377 | }, 1378 | "time": "2024-08-16T06:48:03+00:00" 1379 | }, 1380 | { 1381 | "name": "symfony/deprecation-contracts", 1382 | "version": "v3.5.0", 1383 | "source": { 1384 | "type": "git", 1385 | "url": "https://github.com/symfony/deprecation-contracts.git", 1386 | "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" 1387 | }, 1388 | "dist": { 1389 | "type": "zip", 1390 | "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", 1391 | "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", 1392 | "shasum": "" 1393 | }, 1394 | "require": { 1395 | "php": ">=8.1" 1396 | }, 1397 | "type": "library", 1398 | "extra": { 1399 | "branch-alias": { 1400 | "dev-main": "3.5-dev" 1401 | }, 1402 | "thanks": { 1403 | "name": "symfony/contracts", 1404 | "url": "https://github.com/symfony/contracts" 1405 | } 1406 | }, 1407 | "autoload": { 1408 | "files": [ 1409 | "function.php" 1410 | ] 1411 | }, 1412 | "notification-url": "https://packagist.org/downloads/", 1413 | "license": [ 1414 | "MIT" 1415 | ], 1416 | "authors": [ 1417 | { 1418 | "name": "Nicolas Grekas", 1419 | "email": "p@tchwork.com" 1420 | }, 1421 | { 1422 | "name": "Symfony Community", 1423 | "homepage": "https://symfony.com/contributors" 1424 | } 1425 | ], 1426 | "description": "A generic function and convention to trigger deprecation notices", 1427 | "homepage": "https://symfony.com", 1428 | "support": { 1429 | "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" 1430 | }, 1431 | "funding": [ 1432 | { 1433 | "url": "https://symfony.com/sponsor", 1434 | "type": "custom" 1435 | }, 1436 | { 1437 | "url": "https://github.com/fabpot", 1438 | "type": "github" 1439 | }, 1440 | { 1441 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 1442 | "type": "tidelift" 1443 | } 1444 | ], 1445 | "time": "2024-04-18T09:32:20+00:00" 1446 | }, 1447 | { 1448 | "name": "symfony/polyfill-mbstring", 1449 | "version": "v1.31.0", 1450 | "source": { 1451 | "type": "git", 1452 | "url": "https://github.com/symfony/polyfill-mbstring.git", 1453 | "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" 1454 | }, 1455 | "dist": { 1456 | "type": "zip", 1457 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", 1458 | "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", 1459 | "shasum": "" 1460 | }, 1461 | "require": { 1462 | "php": ">=7.2" 1463 | }, 1464 | "provide": { 1465 | "ext-mbstring": "*" 1466 | }, 1467 | "suggest": { 1468 | "ext-mbstring": "For best performance" 1469 | }, 1470 | "type": "library", 1471 | "extra": { 1472 | "thanks": { 1473 | "name": "symfony/polyfill", 1474 | "url": "https://github.com/symfony/polyfill" 1475 | } 1476 | }, 1477 | "autoload": { 1478 | "files": [ 1479 | "bootstrap.php" 1480 | ], 1481 | "psr-4": { 1482 | "Symfony\\Polyfill\\Mbstring\\": "" 1483 | } 1484 | }, 1485 | "notification-url": "https://packagist.org/downloads/", 1486 | "license": [ 1487 | "MIT" 1488 | ], 1489 | "authors": [ 1490 | { 1491 | "name": "Nicolas Grekas", 1492 | "email": "p@tchwork.com" 1493 | }, 1494 | { 1495 | "name": "Symfony Community", 1496 | "homepage": "https://symfony.com/contributors" 1497 | } 1498 | ], 1499 | "description": "Symfony polyfill for the Mbstring extension", 1500 | "homepage": "https://symfony.com", 1501 | "keywords": [ 1502 | "compatibility", 1503 | "mbstring", 1504 | "polyfill", 1505 | "portable", 1506 | "shim" 1507 | ], 1508 | "support": { 1509 | "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" 1510 | }, 1511 | "funding": [ 1512 | { 1513 | "url": "https://symfony.com/sponsor", 1514 | "type": "custom" 1515 | }, 1516 | { 1517 | "url": "https://github.com/fabpot", 1518 | "type": "github" 1519 | }, 1520 | { 1521 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 1522 | "type": "tidelift" 1523 | } 1524 | ], 1525 | "time": "2024-09-09T11:45:10+00:00" 1526 | }, 1527 | { 1528 | "name": "symfony/polyfill-php82", 1529 | "version": "v1.31.0", 1530 | "source": { 1531 | "type": "git", 1532 | "url": "https://github.com/symfony/polyfill-php82.git", 1533 | "reference": "5d2ed36f7734637dacc025f179698031951b1692" 1534 | }, 1535 | "dist": { 1536 | "type": "zip", 1537 | "url": "https://api.github.com/repos/symfony/polyfill-php82/zipball/5d2ed36f7734637dacc025f179698031951b1692", 1538 | "reference": "5d2ed36f7734637dacc025f179698031951b1692", 1539 | "shasum": "" 1540 | }, 1541 | "require": { 1542 | "php": ">=7.2" 1543 | }, 1544 | "type": "library", 1545 | "extra": { 1546 | "thanks": { 1547 | "name": "symfony/polyfill", 1548 | "url": "https://github.com/symfony/polyfill" 1549 | } 1550 | }, 1551 | "autoload": { 1552 | "files": [ 1553 | "bootstrap.php" 1554 | ], 1555 | "psr-4": { 1556 | "Symfony\\Polyfill\\Php82\\": "" 1557 | }, 1558 | "classmap": [ 1559 | "Resources/stubs" 1560 | ] 1561 | }, 1562 | "notification-url": "https://packagist.org/downloads/", 1563 | "license": [ 1564 | "MIT" 1565 | ], 1566 | "authors": [ 1567 | { 1568 | "name": "Nicolas Grekas", 1569 | "email": "p@tchwork.com" 1570 | }, 1571 | { 1572 | "name": "Symfony Community", 1573 | "homepage": "https://symfony.com/contributors" 1574 | } 1575 | ], 1576 | "description": "Symfony polyfill backporting some PHP 8.2+ features to lower PHP versions", 1577 | "homepage": "https://symfony.com", 1578 | "keywords": [ 1579 | "compatibility", 1580 | "polyfill", 1581 | "portable", 1582 | "shim" 1583 | ], 1584 | "support": { 1585 | "source": "https://github.com/symfony/polyfill-php82/tree/v1.31.0" 1586 | }, 1587 | "funding": [ 1588 | { 1589 | "url": "https://symfony.com/sponsor", 1590 | "type": "custom" 1591 | }, 1592 | { 1593 | "url": "https://github.com/fabpot", 1594 | "type": "github" 1595 | }, 1596 | { 1597 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 1598 | "type": "tidelift" 1599 | } 1600 | ], 1601 | "time": "2024-09-09T11:45:10+00:00" 1602 | }, 1603 | { 1604 | "name": "theodo-group/llphant", 1605 | "version": "0.8.12", 1606 | "source": { 1607 | "type": "git", 1608 | "url": "https://github.com/theodo-group/LLPhant.git", 1609 | "reference": "3fa0188f347c6f77433577f17f40e341bf45e4cc" 1610 | }, 1611 | "dist": { 1612 | "type": "zip", 1613 | "url": "https://api.github.com/repos/theodo-group/LLPhant/zipball/3fa0188f347c6f77433577f17f40e341bf45e4cc", 1614 | "reference": "3fa0188f347c6f77433577f17f40e341bf45e4cc", 1615 | "shasum": "" 1616 | }, 1617 | "require": { 1618 | "guzzlehttp/guzzle": "^7.4.5", 1619 | "guzzlehttp/psr7": "^2.7", 1620 | "openai-php/client": "^v0.10.1", 1621 | "php": "^8.1.0", 1622 | "phpoffice/phpword": "^1.3.0", 1623 | "psr/http-message": "^2.0", 1624 | "smalot/pdfparser": "^2.7" 1625 | }, 1626 | "require-dev": { 1627 | "codewithkyrian/chromadb-php": "^0.3.0", 1628 | "doctrine/orm": "^2.20.0", 1629 | "elasticsearch/elasticsearch": "^8.15", 1630 | "hkulekci/qdrant": "^v0.5.7", 1631 | "laravel/pint": "v1.15.3", 1632 | "mockery/mockery": "^1.6.12", 1633 | "opensearch-project/opensearch-php": "^2.3", 1634 | "pestphp/pest": "^v2.36.0", 1635 | "pestphp/pest-plugin-arch": "^2.7.0", 1636 | "pestphp/pest-plugin-type-coverage": "2.8.0", 1637 | "phpstan/phpstan": "1.10.55", 1638 | "predis/predis": "^2.2", 1639 | "rector/rector": "^0.16.0", 1640 | "symfony/cache": "^7.2", 1641 | "symfony/process": "^v7.1.8", 1642 | "symfony/var-dumper": "^7.2" 1643 | }, 1644 | "suggest": { 1645 | "codewithkyrian/chromadb-php": "This is required for the ChromaDBVectorStore.", 1646 | "doctrine/orm": "This is required for the DoctrineVectoreStore. This should be working with any version ^2.13.0", 1647 | "elasticsearch/elasticsearch": "This is required for the ElasticsearchVectoreStore.", 1648 | "hkulekci/qdrant": "This is required for the QdrantVectoreStore.", 1649 | "opensearch-project/opensearch-php": "This is required for the OpenSearchVectorStore.", 1650 | "predis/predis": "This is required for the RedisVectoreStore.", 1651 | "symfony/cache": "This is one of the possible types of psr/cache needed by doctrine/orm" 1652 | }, 1653 | "type": "library", 1654 | "autoload": { 1655 | "psr-4": { 1656 | "LLPhant\\": "src/" 1657 | } 1658 | }, 1659 | "notification-url": "https://packagist.org/downloads/", 1660 | "license": [ 1661 | "MIT" 1662 | ], 1663 | "authors": [ 1664 | { 1665 | "name": "Maxime Thoonsen" 1666 | } 1667 | ], 1668 | "description": "LLPhant is a library to help you build Generative AI applications.", 1669 | "keywords": [ 1670 | "anthropic", 1671 | "api", 1672 | "gpt-4", 1673 | "language", 1674 | "llm", 1675 | "mistral", 1676 | "ollama", 1677 | "openai", 1678 | "php", 1679 | "vectorstore" 1680 | ], 1681 | "support": { 1682 | "issues": "https://github.com/theodo-group/LLPhant/issues", 1683 | "source": "https://github.com/theodo-group/LLPhant/tree/0.8.12" 1684 | }, 1685 | "time": "2024-11-23T13:58:39+00:00" 1686 | } 1687 | ], 1688 | "packages-dev": [], 1689 | "aliases": [], 1690 | "minimum-stability": "stable", 1691 | "stability-flags": [], 1692 | "prefer-stable": false, 1693 | "prefer-lowest": false, 1694 | "platform": { 1695 | "php": "^8.1" 1696 | }, 1697 | "platform-dev": [], 1698 | "plugin-api-version": "2.3.0" 1699 | } 1700 | -------------------------------------------------------------------------------- /data/nobel_prize_physics_2024.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ezimuel/llphant-llama-elasticsearch/e2f546e0dc883317622f3cdca263eecec70f2655/data/nobel_prize_physics_2024.pdf -------------------------------------------------------------------------------- /src/embedding.php: -------------------------------------------------------------------------------- 1 | model = 'llama3.2'; 18 | $chat = new OllamaChat($config); 19 | 20 | # Read PDF file 21 | printf ("- Reading the PDF files\n"); 22 | $reader = new FileDataReader(dirname(__DIR__) . '/data/nobel_prize_physics_2024.pdf'); 23 | $documents = $reader->getDocuments(); 24 | printf("Number of PDF files: %d\n", count($documents)); 25 | 26 | # Document split 27 | printf("- Document split\n"); 28 | $splitDocuments = DocumentSplitter::splitDocuments($documents, 800); 29 | printf("Number of splitted documents (chunk): %d\n", count($splitDocuments)); 30 | 31 | # Embedding 32 | printf("- Embedding\n"); 33 | $embeddingGenerator = new OllamaEmbeddingGenerator($config); 34 | $embeddedDocuments = $embeddingGenerator->embedDocuments($splitDocuments); 35 | 36 | # Read the .env file 37 | $env = read_env_file(dirname(__DIR__) . '/elastic-start-local/.env'); 38 | 39 | # Elasticsearch 40 | printf("- Index all the embeddings to Elasticsearch\n"); 41 | $es = (new ClientBuilder())::create() 42 | ->setHosts([$env['ES_LOCAL_URL']]) 43 | ->setApiKey($env['ES_LOCAL_API_KEY']) 44 | ->build(); 45 | 46 | $elasticVectorStore = new ElasticsearchVectorStore($es, $indexName = 'nobel'); 47 | $elasticVectorStore->addDocuments($embeddedDocuments); 48 | 49 | printf("Added %d documents in Elasticsearch with embedding included\n", count($embeddedDocuments)); -------------------------------------------------------------------------------- /src/qa.php: -------------------------------------------------------------------------------- 1 | model = 'llama3.2'; 17 | $config->modelOptions = [ 18 | 'options' => [ 19 | 'temperature' => 0 20 | ] 21 | ]; 22 | $chat = new OllamaChat($config); 23 | 24 | # Embedding 25 | $embeddingGenerator = new OllamaEmbeddingGenerator($config); 26 | 27 | # Read the .env file 28 | $env = read_env_file(dirname(__DIR__) . '/elastic-start-local/.env'); 29 | 30 | # Elasticsearch 31 | $es = (new ClientBuilder())::create() 32 | ->setHosts([$env['ES_LOCAL_URL']]) 33 | ->setApiKey($env['ES_LOCAL_API_KEY']) 34 | ->build(); 35 | 36 | $elasticVectorStore = new ElasticsearchVectorStore($es, $indexName = 'nobel'); 37 | 38 | # RAG 39 | $qa = new QuestionAnswering( 40 | $elasticVectorStore, 41 | $embeddingGenerator, 42 | $chat 43 | ); 44 | 45 | $answer = $qa->answerQuestion('Who won the Nobel Prize in Physics in 2024?'); 46 | printf("-- Answer:\n%s\n", $answer); 47 | printf("\n"); 48 | $retrievedDocs = $qa->getRetrievedDocuments(); 49 | printf("We used %d documents to answer the question, as follows:\n\n", count($retrievedDocs)); 50 | foreach ($qa->getRetrievedDocuments() as $doc) { 51 | printf("-- Document: %s\n", $doc->sourceName); 52 | printf("-- Hash: %s\n", $doc->hash); 53 | printf("-- Content of %d characters, extract: %s...\n\n", strlen($doc->content), substr($doc->content, 0, 100)); 54 | } 55 | -------------------------------------------------------------------------------- /src/utility.php: -------------------------------------------------------------------------------- 1 |