From 643c0c5791a2fb9a4734798c295dcaadfd0cdff6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bohuslav=20=C5=A0imek?= Date: Sat, 22 Apr 2023 18:18:03 +0200 Subject: [PATCH] feat(LLM.php): add abstract call method to LLM class feat(llm-LLaMACpp.php): add example usage of LLaMACpp class with a prompt text feat(LLaMACpp.php): add LLaMACpp class implementation with constructor, defaultParams, call, llmType, toArray, and getIdentifyingParams methods. --- README.md | 2 +- examples/llm-LLaMACpp.php | 9 ++ src/LLMs/LLM.php | 41 +++++++++ src/LLMs/LLaMACpp.php | 186 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 237 insertions(+), 1 deletion(-) create mode 100644 examples/llm-LLaMACpp.php create mode 100644 src/LLMs/LLM.php create mode 100644 src/LLMs/LLaMACpp.php diff --git a/README.md b/README.md index e11f920..70aabe2 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ This library is still in development. Use at your own risk! ### Supported features * Prompt formatting -* LLMs: OpenAI GPT-3, ChatGPT +* LLMs: OpenAI GPT-3, ChatGPT, llama.cpp * Vector stores: Simple stupid vector store * Texts splitters: CharacterTextSplitter, RecursiveCharacterTextSplitter * Embeddings: OpenAI diff --git a/examples/llm-LLaMACpp.php b/examples/llm-LLaMACpp.php new file mode 100644 index 0000000..67811d3 --- /dev/null +++ b/examples/llm-LLaMACpp.php @@ -0,0 +1,9 @@ + 'path/to/model.bin']); +$text = "What's the best programing language for web?"; +echo $llm($text); diff --git a/src/LLMs/LLM.php b/src/LLMs/LLM.php new file mode 100644 index 0000000..81b4b7c --- /dev/null +++ b/src/LLMs/LLM.php @@ -0,0 +1,41 @@ +call($prompt, ['stop' => $stop]); + $generations[] = new Generation( + $result, + ); + } + + return new LLMResult([$generations], []); + } +} diff --git a/src/LLMs/LLaMACpp.php b/src/LLMs/LLaMACpp.php new file mode 100644 index 0000000..0361678 --- /dev/null +++ b/src/LLMs/LLaMACpp.php @@ -0,0 +1,186 @@ +modelPath = $options['model_path'] ?? $this->modelPath; + $this->nCtx = $options['n_ctx'] ?? $this->nCtx; + $this->nParts = $options['n_parts'] ?? $this->nParts; + $this->seed = $options['seed'] ?? $this->seed; + $this->f16Kv = $options['f16_kv'] ?? $this->f16Kv; + $this->logitsAll = $options['logits_all'] ?? $this->logitsAll; + $this->vocabOnly = $options['vocab_only'] ?? $this->vocabOnly; + $this->useMlock = $options['use_mlock'] ?? $this->useMlock; + $this->nThreads = $options['n_threads'] ?? $this->nThreads; + $this->nBatch = $options['n_batch'] ?? $this->nBatch; + $this->suffix = $options['suffix'] ?? $this->suffix; + $this->maxTokens = $options['max_tokens'] ?? $this->maxTokens; + $this->temperature = $options['temperature'] ?? $this->temperature; + $this->topP = $options['top_p'] ?? $this->topP; + $this->logprobs = $options['logprobs'] ?? $this->logprobs; + $this->echo = $options['echo'] ?? $this->echo; + $this->stop = $options['stop'] ?? $this->stop; + $this->repeatPenalty = $options['repeat_penalty'] ?? $this->repeatPenalty; + $this->topK = $options['top_k'] ?? $this->topK; + $this->lastNTokensSize = $options['last_n_tokens_size'] ?? $this->lastNTokensSize; + + parent::__construct($options, $callbackManager, $cache); + + if ($adapter === null) { + $adapter = LLamaCPPLangchainAdapter::create( + [ + 'model_path' => $this->modelPath, + 'n_ctx' => $this->nCtx, + 'n_parts' => $this->nParts, + 'seed' => $this->seed, + 'f16_kv' => $this->f16Kv, + 'logits_all' => $this->logitsAll, + 'vocab_only' => $this->vocabOnly, + 'use_mlock' => $this->useMlock, + 'n_threads' => $this->nThreads, + ] + ); + } + + $this->adapter = $adapter; + } + + /** + * Returns the default parameters for the model. + * @return array + */ + private function defaultParams() + { + return [ + 'suffix' => $this->suffix, + 'max_tokens' => $this->maxTokens, + 'temperature' => $this->temperature, + 'top_p' => $this->topP, + 'logprobs' => $this->logprobs, + 'echo' => $this->echo, + 'stop_sequences' => $this->stop, + 'repeat_penalty' => $this->repeatPenalty, + 'top_k' => $this->topK, + ]; + } + + /** + * Call the Llama model and return the output. + * + * @param string $prompt The prompt to use for generation. + * @param mixed $stop A list of strings to stop generation when encountered. + * + * @return string The generated text. + */ + public function call(string $prompt, $stop = null): string + { + $params = $this->defaultParams(); + + if ($this->stop && $stop !== null) { + throw new InvalidArgumentException('`stop` found in both the input and default params.'); + } elseif ($this->stop) { + $params['stop_sequences'] = $this->stop; + } elseif ($stop !== null) { + $params['stop_sequences'] = $stop; + } else { + $params['stop_sequences'] = []; + } + + $text = $this->adapter->predict($prompt, $params); + + return $text; + } + + public function llmType(): string + { + return 'llama.cpp'; + } + + public function toArray(): array + { + return $this->getIdentifyingParams(); + } + + public function getIdentifyingParams(): array + { + return array_merge(['model_path' => $this->modelPath], $this->defaultParams()); + } +}