cloudsthere / llphant
LLPhant 是一个帮助您构建生成式 AI 应用的库。
Requires
- php: ^8.1.0
- guzzlehttp/guzzle: ^7.1.0
- nunomaduro/termwind: ^1.15
- openai-php/client: ^v0.7.7 || ^v0.8.0
- phpoffice/phpword: ^1.1
- smalot/pdfparser: ^2.7
- symfony/cache: *
- symfony/http-foundation: ^6.0.0 || ^7.0.0
Requires (Dev)
- doctrine/orm: ^2.13.0
- elasticsearch/elasticsearch: ^8.10
- guzzlehttp/psr7: ^2.5.0
- hkulekci/qdrant: ^v0.4
- laravel/pint: ^v1.13.7
- nunomaduro/collision: ^7.7.0
- pestphp/pest: dev-develop as 2.6.2
- pestphp/pest-plugin-arch: ^2.2.1
- pestphp/pest-plugin-mock: ^2.0.0
- pestphp/pest-plugin-type-coverage: ^2.0.0
- phpstan/phpstan: ^1.10.25
- predis/predis: ^2.2
- rector/rector: ^0.16.0
- symfony/var-dumper: ^6.3.1 || ^7.0.0
Suggests
- doctrine/orm: This is required for the DoctrineVectoreStore. This should be working with any version ^2.13.0
- elasticsearch/elasticsearch: This is required for the ElasticsearchVectoreStore.
- hkulekci/qdrant: This is required for the QdrantVectoreStore.
- predis/predis: This is required for the RedisVectoreStore.
README

我们设计了这个框架,使其尽可能简单,同时仍然为您提供构建强大应用程序所需的工具。它与 Symfony 和 Laravel 兼容。
目前仅支持 OpenAI,如果您想使用其他 LLM,可以使用 genossGPT 作为代理。
我们想要感谢一些优秀的项目,这些项目在这里或启发了我们
- 使用 LangChain 和 LLamaIndex 的经验
- 来自 OpenAI PHP SDK 的出色工作。
目录
入门
需要 PHP 8.1+
首先,通过 Composer 包管理器安装 LLPhant
composer require theodo-group/llphant
您可能还需要检查 OpenAI PHP SDK 的要求,因为它是主要的客户端。
用例
生成式 AI 有很多用例,每天都有新的用例出现。让我们看看最常见的一些。根据 MLOPS 社区的调查 和 麦肯锡的调查,最常见的 AI 用例如下
- 创建能够在大量数据中找到相关信息的语义搜索。例如:Slite
- 创建聊天机器人/增强型常见问题解答,它们使用语义搜索和文本摘要来回答客户问题。例如:Quivr 正在使用类似的技术。
- 为客户创建个性化内容(产品页面、电子邮件、消息等)。例如 Carrefour。
- 创建可以将长文本总结成短文本的文本摘要器。
尚未广泛传播,但采用率正在增加
- 创建增强型电商体验的个人购物助手。例如:Madeline
- 创建可以自主执行各种任务的 AI 代理。例如:AutoGpt
- 创建可以帮助您编写或审查代码的编码工具。例如:Code Review GPT
如果您想发现社区中的更多用法,您可以在GenAI Meetups 这里查看列表。您还可以在 Qdrant 的网站上 看到其他用例。
用法
最简单的方法是设置 OPENAI_API_KEY 环境变量来调用 OpenAI。
export OPENAI_API_KEY=sk-XXXXXX
您还可以创建一个 OpenAIConfig 对象并将其传递给 OpenAIChat 或 OpenAIEmbeddings 的构造函数。
$config = new OpenAIConfig(); $config->apiKey = 'fakeapikey'; $chat = new OpenAIChat($config);
聊天
💡 此类可以用于生成内容、创建聊天机器人或创建文本摘要器。
使用OpenAI生成文本的API仅限于聊天API。因此,即使您想要在内部为简单问题生成补全,它也将使用聊天API。这就是为什么这个类被称为OpenAIChat。我们可以用它简单地根据提示生成文本。
这将直接向LLM请求答案。
$chat = new OpenAIChat(); $response = $chat->generateText('what is one + one ?'); // will return something like "Two"
如果您想在您的前端显示类似于ChatGPT的文本流,可以使用以下方法。
$chat = new OpenAIChat(); return $chat->generateStreamOfText('can you write me a poem of 10 lines about life ?');
您可以添加指令,以便LLM以特定方式行事。
$chat = new OpenAIChat(); $chat->setSystemMessage('Whatever we ask you, you MUST answer "ok"'); $response = $chat->generateText('what is one + one ?'); // will return "ok"
工具
这个功能非常神奇。
OpenAI已改进其模型以确定是否应调用工具。要利用此功能,只需向OpenAI发送可用工具的描述即可,可以是单个提示,也可以在更广泛的对话中发送。
在响应中,如果模型认为应该调用一个或多个工具,它将提供被调用的工具名称以及参数值。
一个潜在的应用是确定用户在支持互动期间是否有额外的查询。更令人印象深刻的是,它可以根据用户查询自动执行操作。
我们使这个功能的使用尽可能简单。
让我们看看如何使用它的例子。想象你有一个发送电子邮件的类。
class MailerExample { /** * This function send an email */ public function sendMail(string $subject, string $body, string $email): void { echo 'The email has been sent to '.$email.' with the subject '.$subject.' and the body '.$body.'.'; } }
您可以创建一个FunctionInfo对象来描述您的方法给OpenAI。然后,您可以将它添加到OpenAIChat对象中。如果OpenAI的响应包含工具的名称和参数,LLPhant将调用该工具。

此PHP脚本很可能调用我们传递给OpenAI的sendMail方法。
$chat = new OpenAIChat(); // This helper will automatically gather information to describe the tools $tool = FunctionBuilder::buildFunctionInfo(new MailerExample(), 'sendMail'); $chat->addTool($tool); $chat->setSystemMessage('You are an AI that deliver information using the email system. When you have enough information to answer the question of the user you send a mail'); $chat->generateText('Who is Marie Curie in one line? My email is student@foo.com');
如果您想对函数的描述有更多控制,您可以手动构建它。
$chat = new OpenAIChat(); $subject = new Parameter('subject', 'string', 'the subject of the mail'); $body = new Parameter('body', 'string', 'the body of the mail'); $email = new Parameter('email', 'string', 'the email address'); $tool = new FunctionInfo( 'sendMail', new MailerExample(), 'send a mail', [$subject, $body, $email] ); $chat->addTool($tool); $chat->setSystemMessage('You are an AI that deliver information using the email system. When you have enough information to answer the question of the user you send a mail'); $chat->generateText('Who is Marie Curie in one line? My email is student@foo.com');
您可以在Parameter对象中安全地使用以下类型:string,int,float,bool。数组类型受支持,但仍在实验中。
嵌入
💡嵌入用于比较两个文本并查看它们有多相似。这是语义搜索的基础。嵌入是文本的向量表示,它捕获了文本的意义。对于OpenAI,它是1536个元素的浮点数组。
为了操作嵌入,我们使用包含文本和一些对向量存储有用的元数据的Document
类。创建嵌入的流程如下

读取数据
流程的第一步是从来源读取数据。这可以是数据库、csv文件、json文件、文本文件、网站、pdf、word文档、excel文件等。唯一的要求是可以读取数据,并且可以从其中提取文本。
目前我们只支持文本文件、pdf和docx,但我们计划在未来支持其他数据类型。
您可以使用FileDataReader
类读取文件。它接受一个文件路径或目录作为参数。第二个参数是用于存储嵌入的实体的类名。该类需要扩展Document
类,如果想要使用Doctrine向量存储,还需要扩展DoctrineEmbeddingEntityBase
类(它扩展了Document
类)。
$filePath = __DIR__.'/PlacesTextFiles'; $reader = new FileDataReader($filePath, PlaceEntity::class); $documents = $reader->getDocuments();
要创建自己的数据读取器,您需要创建一个实现DataReader
接口的类。
文档分割器
嵌入模型有一个它们可以处理的字符串大小限制。为了避免这个问题,我们将文档分割成更小的块。DocumentSplitter
类用于将文档分割成更小的块。
$splittedDocuments = DocumentSplitter::splitDocuments($documents, 800);
嵌入格式化器
EmbeddingFormatter
是一个可选步骤,用于将每个文本块格式化为具有最多上下文格式的格式。添加标题和其他文档的链接可以帮助LLM理解文本的上下文。
$formattedDocuments = EmbeddingFormatter::formatEmbeddings($splittedDocuments);
嵌入生成器
这是通过调用LLM为每个文本块生成嵌入的步骤。
您可以使用以下代码嵌入文档
$embeddingGenerator = new OpenAIEmbeddingGenerator(); $embededDocuments = $embeddingGenerator->embedDocuments($formattedDocuments);
您还可以使用以下代码从文本创建嵌入
$llm = new OpenAIEmbeddingGenerator(); $embedding = $llm->embedText('I love food'); //You can then use the embedding to perform a similarity search
VectorStores
一旦您有了嵌入,就需要将它们存储在向量存储中。向量存储是一个数据库,可以存储向量和执行相似度搜索。目前有4个向量存储类
- MemoryVectorStore在内存中存储嵌入
- FileSystemVectorStore在文件中存储嵌入
- DoctrineVectorStore在postgresql数据库中存储嵌入。(需要 doctrine/orm)
- QdrantVectorStore在Qdrant向量存储中存储嵌入。(需要hkulekci/qdrant)
- RedisVectorStore在Redis数据库中存储嵌入。(需要predis/predis)
- ElasticsearchVectorStore在Elasticsearch数据库中存储嵌入。(需要elasticsearch/elasticsearch)
- MilvusVectorStore在Milvus数据库中存储嵌入。
使用DoctrineVectorStore
类将嵌入存储在数据库中的示例
$vectorStore = new DoctrineVectorStore($entityManager, PlaceEntity::class); $vectorStore->addDocuments($embededDocuments);
完成这些后,您可以在数据上执行相似度搜索。您需要传递要搜索的文本的嵌入以及您想要获取的结果数量。
$embedding = $embeddingGenerator->embedText('France the country'); /** @var PlaceEntity[] $result */ $result = $vectorStore->similaritySearch($embedding, 2);
要获取完整的示例,您可以查看Doctrine集成测试文件。
Doctrine VectorStore
对于Web开发者来说,一个简单的解决方案是使用带有pgvector扩展的postgresql数据库作为vectorStore。您可以在其github仓库上找到有关pgvector扩展的所有信息。
我们建议您使用以下3种简单方法来获取启用扩展的postgresql数据库
- 使用docker-compose-pgvector.yml文件使用docker
- 使用Supabase
- 使用Neon
在任何情况下,您都需要激活扩展
CREATE EXTENSION IF NOT EXISTS vector;
然后您可以创建一个表并存储向量。此sql查询将在测试文件夹中的PlaceEntity创建相应的表。
CREATE TABLE IF NOT EXISTS test_place ( id SERIAL PRIMARY KEY, content TEXT, type TEXT, sourcetype TEXT, sourcename TEXT, embedding VECTOR );
The PlaceEntity
#[Entity] #[Table(name: 'test_place')] class PlaceEntity extends DoctrineEmbeddingEntityBase { #[ORM\Column(type: Types::STRING, nullable: true)] public ?string $type; }
Redis VectorStore
先决条件
然后使用您的服务器凭据创建一个新的Redis客户端,并将其传递给RedisVectorStore构造函数
use Predis\Client; $redisClient = new Client([ 'scheme' => 'tcp', 'host' => 'localhost', 'port' => 6379, ]); $vectorStore = new RedisVectorStore($redisClient, 'llphant_custom_index'); // The default index is llphant
现在您可以使用RedisVectorStore作为任何其他VectorStore。
Elasticsearch VectorStore
先决条件
- Elasticsearch服务器正在运行(见Elasticsearch快速入门)
- Elasticsearch PHP客户端已安装(见Elasticsearch PHP客户端)
然后使用您的服务器凭据创建一个新的Elasticsearch客户端,并将其传递给ElasticsearchVectorStore构造函数
use Elastic\Elasticsearch\ClientBuilder; $client = (new ClientBuilder())::create() ->setHosts(['https://:9200']) ->build(); $vectorStore = new ElasticsearchVectorStore($client, 'llphant_custom_index'); // The default index is llphant
现在您可以使用ElasticsearchVectorStore作为任何其他VectorStore。
Milvus VectorStore
先决条件:Milvus服务器正在运行(见Milvus文档)
然后创建一个新的Milvus客户端(LLPhant\Embeddings\VectorStores\Milvus\MilvusClient
)并使用您的服务器凭据,将其传递给MilvusVectorStore构造函数
$client = new MilvusClient('localhost', '19530', 'root', 'milvus'); $vectorStore = new MilvusVectorStore($client);
您现在可以将 MilvusVectorStore 当作任何其他 VectorStore 使用。
问答
LLM 的一个常见用法是创建一个聊天机器人,该机器人可以回答关于您私人数据的问题。您可以使用 LLPhant 和 QuestionAnswering
类来构建一个聊天机器人。它利用向量存储进行相似度搜索,以获取最相关的信息,并返回由 OpenAI 生成的答案。

以下是一个使用 MemoryVectorStore
的示例。
$dataReader = new FileDataReader(__DIR__.'/private-data.txt'); $documents = $dataReader->getDocuments(); $splittedDocuments = DocumentSplitter::splitDocuments($documents, 500); $embeddingGenerator = new OpenAIEmbeddingGenerator(); $embeddedDocuments = $embeddingGenerator->embedDocuments($splittedDocuments); $memoryVectorStore = new MemoryVectorStore(); $memoryVectorStore->addDocuments($embeddedDocuments); //Once the vectorStore is ready, you can then use the QuestionAnswering class to answer questions $qa = new QuestionAnswering( $memoryVectorStore, $embeddingGenerator, new OpenAIChat() ); $answer = $qa->answerQuestion('what is the secret of Alice?');
AutoPHP
您现在可以使用 LLPhant 在 PHP 中创建您的 AutoGPT 克隆。
以下是一个使用 SerpApiSearch 工具创建自主 PHP 代理的简单示例。您只需描述目标并添加您想要使用的工具。我们将在未来添加更多工具。
use LLPhant\Chat\FunctionInfo\FunctionBuilder; use LLPhant\Experimental\Agent\AutoPHP; use LLPhant\Tool\SerpApiSearch; require_once 'vendor/autoload.php'; // You describe the objective $objective = 'Find the names of the wives or girlfriends of at least 2 players from the 2023 male French football team.'; // You can add tools to the agent, so it can use them. You need an API key to use SerpApiSearch // Have a look here: https://serpapi.com $searchApi = new SerpApiSearch(); $function = FunctionBuilder::buildFunctionInfo($searchApi, 'search'); $autoPHP = new AutoPHP($objective, [$function]); $autoPHP->run();
常见问题解答(FAQ)
为什么使用 LLPhant 而不是直接使用 OpenAI PHP SDK?
OpenAI PHP SDK 是一个与 OpenAI API 交互的出色工具。LLphant 允许您执行诸如存储嵌入和执行相似度搜索等复杂任务。它还通过提供一个更简单的 API 来简化 OpenAI API 的使用,该 API 适用于日常使用。
贡献者
感谢我们的贡献者
赞助商
LLPhant 由领先的数字代理公司 Theodo 赞助,该公司专注于构建使用生成式 AI 的 Web 应用程序。