cloudsthere/llphant

LLPhant 是一个帮助您构建生成式 AI 应用的库。

v0.0.1 2024-01-06 13:45 UTC

This package is auto-updated.

Last update: 2024-09-13 13:42:15 UTC


README

LLPhant

我们设计了这个框架,使其尽可能简单,同时仍然为您提供构建强大应用程序所需的工具。它与 Symfony 和 Laravel 兼容。

目前仅支持 OpenAI,如果您想使用其他 LLM,可以使用 genossGPT 作为代理。

我们想要感谢一些优秀的项目,这些项目在这里或启发了我们

目录

入门

需要 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将调用该工具。

Function flow

此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类。创建嵌入的流程如下

Embeddings flow

读取数据

流程的第一步是从来源读取数据。这可以是数据库、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数据库

在任何情况下,您都需要激活扩展

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客户端,并将其传递给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 生成的答案。

Question Answering flow

以下是一个使用 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 应用程序。

Theodo logo