manuelkiessling / ai-tool-bridge
无缝提升您的AI集成能力,使其与您的代码和服务交互
Requires
- php: ^8.2
- ext-mbstring: *
Requires (Dev)
- phpunit/phpunit: ^10.1
This package is auto-updated.
Last update: 2024-09-30 01:52:22 UTC
README
无缝提升您的AI集成能力,使其与您的代码和服务交互
注意:本产品为独立开发,与OpenAI无关,未获得其认可、赞助或支持。
安装
使用 Composer 将此包作为依赖项安装。
composer require manuelkiessling/ai-tool-bridge
概述
将AI集成到任何项目的主要挑战是管理AI与应用程序其他部分的交互。当AI需要调用API以检索信息或触发操作时,这变得尤为复杂。
PHP的AI Tool Bridge优雅地解决了这个问题,它提供了一个简单的接口来定义AI可以利用的“工具函数”,以便在与外部系统交互时使用。
一个重要的优化是库能够生成工具函数所需的JSON结构。它通过仅从AI请求所需值,然后根据提供的JSON模式生成JSON来完成。这种方法确保了最终到达您的应用程序代码的JSON的有效性。
此库的关键特性包括
- 促进定义AI可以用于外部交互的工具。
- 提供强大的提示结构,以指导AI何时以及如何使用这些工具。
- 确保工具以完整和正确格式化的JSON触发。
示例
假设您有一家电商业务,并希望提供一个AI聊天界面,允许浏览您的产品目录。为此,您决定通过ChatGPT API与OpenAI的GPT-4模型集成。
您可能会提示AI助手“您是一个友好而乐于助人的购物助手,向用户介绍我们的产品目录...”等等。
但是,您不能将整个产品目录添加到提示中。因此,当用户要求AI“告诉我一些在售的厨房助手”时,您需要识别在这个对话阶段,AI需要从您的电商后端系统(例如,通过向您的产品搜索API发出带有查询“厨房助手”的请求)获取信息,您需要为AI检索这些信息,并将结果信息返回给AI助手,然后AI助手可以为用户总结产品信息。
AI最清楚何时需要从外部世界获取这些信息。由于让您的代码监听对话并猜测何时进行产品搜索API调用既复杂又容易出错,这使使用强大AI的想法变得有些毫无意义。
最佳方法是让AI认识到与外部世界交谈的时机已经到来,并以结构化和明确的方式进行。
解决方案是在初始系统提示中教会AI,它有一或多个工具可供使用。
这是通过首先编写所谓的工具函数定义来完成的,如下所示
<?php declare(strict_types=1); namespace ManuelKiessling\AiToolBridge\Example; use ManuelKiessling\AiToolBridge\ToolFunctionCallResult; use ManuelKiessling\AiToolBridge\ToolFunctionCallResultStatus; use ManuelKiessling\AiToolBridge\ToolFunction; class MyProductSearchToolFunction implements ToolFunction { public function getName(): string { return 'productSearch'; } public function getDescription(): string { return 'allows to search the product catalogue and retrieve information about products'; } public function getInputJsonSchema(): string { return <<<'JSON' { "type": "object", "properties": { "searchterms": { "type": "string" } }, "required": [ "searchterms" ] } JSON; } public function invoke(string $json): ToolFunctionCallResult { // we will talk about this in a minute return new ToolFunctionCallResult( $this, ToolFunctionCallResultStatus::SUCCESS, '', [] ); } }
确保名称、描述和JSON模式中的对象键是有用且描述性的 - 这有助于AI理解何时以及如何使用此工具函数。
您可以定义多个工具函数定义 - 例如,可以添加另一个工具函数,当用户要求时,使AI能够将产品放入购物车。尽管如此,我们将保持此示例简单。
接下来,您需要将工具桥接器与现有的AI设置集成。这是使用AiToolBridge
辅助程序完成的。
class Example { private AiToolBridge $aiToolBridge; private MyAiService $myAiService; public function __construct() { $this->myAiService = new MyAiService(); $myProductSearchToolFunction = new MyProductSearchToolFunction(); $this->aiToolBridge = new AiToolBridge( new $this->myAiService, [$myProductSearchToolFunction], ); $this->myAiService->setSystemPrompt( "You are a friendly and helpful shopping assistant that informs the user about our product catalog... {$this->aiToolBridge->getPrompt()}" ); } }
这显然需要做出几个假设 - 您的应用程序结构和您如何集成AI服务可能会有很大的不同。
尽管如此,集成点始终相同。因为这个库需要能够与AI助手交流,您必须提供一个实现了接口AiAssistantMessenger
的对象。请参阅src/Example/MyAiService.php以获取一个基本示例。
您还需要在创建AiToolBridge对象时附加您定义的工具函数。
接下来,为了使AI理解它可以使用您的工具,您需要将此库生成的提示扩展到您自己的AI“系统”提示中。为此,使用上面显示的方法AiToolBridge::getPrompt
。
您的应用程序和此库现在已完全集成和设置。不过,还缺少一个核心部分 - 当AI使用您的工具函数时应该触发的实际行为。
让我们再次看看类MyProductSearchToolFunction
中的方法invoke
。
public function invoke(string $json): ToolFunctionCallResult { return new ToolFunctionCallResult( $this, ToolFunctionCallResultStatus::SUCCESS, '', [] ); }
这里需要发生魔法 - 也就是说,这是实现所有逻辑的地方 - 您的逻辑 - 以执行实际的产品搜索。
在这里,您根本不需要考虑任何AI集成 - 这正是此库的目的,为您承担重任。
更准确地说,当调用invoke
方法时,繁重的工作已经完成 - 您可以放心,该方法将以一个JSON字符串调用,该字符串一方面具有您在方法MyProductSearchToolFunction::getInputJsonSchema
中定义的精确结构,另一方面填充了AI在使用工具函数时认为有用的值。
因此,例如,如果AI与用户的对话是这样的
AI: Hello, how can I help you?
User: Tell me about some kitchen helpers on offer.
那么AI将认识到它应该使用工具函数productSearch
来搜索kitchen helpers
,这最终导致调用MyProductSearchToolFunction::invoke
并带有以下JSON字符串
{ "searchterms": "kitchen helpers" }
您对如何实现此方法有完全的自由(只要返回一个ToolFunctionCallResult
对象)。在我们的示例中,实际上执行产品搜索显然是有意义的,但如何执行这一点完全取决于您。查询数据库、与API交谈或任何其他检索有关“厨房助手”的生产信息的方法。
您需要返回的ToolFunctionCallResult
对象上的两个感兴趣的领域是message
和data
。在我们的示例中,它可能看起来像这样
public function invoke(string $json): ToolFunctionCallResult { $jsonAsArray = json_decode($json, true); // use $jsonAsArray['searchterm'] when talking to a DB or an API... return new ToolFunctionCallResult( $this, ToolFunctionCallResultStatus::SUCCESS, 'Found 2 matching products', [ [ 'id' => 84, 'name' => 'Kawaii Chick Egg Separator', 'price' => 14.99, 'description' => 'Whether you’re a beginner baker or an experienced cook, the Kawaii Chick Egg Separator is a must-have kitchen tool that will make separating eggs a breeze.' ], [ 'id' => 2389, 'name' => 'BlendJet 2', 'price' => 49.99, 'description' => 'Imagine the freedom of being able to go anywhere and blend your favorite smoothies, shakes, margaritas, frappés, or baby food without the limitations of a regular blender.' ] ] ); }
data
格式不受任何特定模式的限制。
让我们来看看最后一部分,并回到我们的Example
类。我们假设在您的实现中有一个方法handleAssistantMessage
,每当您的应用程序检索到新的AI助手消息时就会调用它 - 这又是您的应用程序的一个非常具体的实现细节。
这是我们在将消息发送给用户之前“挂钩”到对话的地方。这允许工具库检测AI中的任何工具函数请求并相应地处理它。
如果工具函数已调用并成功,我们需要将结果反馈给AI助手 - 这样,它就可以了解与它的产品搜索相匹配的产品。
<?php declare(strict_types=1); class Example { // ... public function handleAssistantMessage(string $message): void { $toolFunctionCallResult = $this->aiToolBridge->handleAssistantMessage($message); if (is_null($toolFunctionCallResult)) { // The AI didn't use a tool function, thus its message is meant for the user $this->sendAssistantMessageToUser($message); } else { // The AI used a tool function, we now need to send the result to the AI $dataAsJson = json_encode($toolFunctionCallResult->data); $this->sendUserMessageToAssistant($toolFunctionCallResult->message . ' ' . $dataAsJson); } } public function sendAssistantMessageToUser(string $message): void { // whatever code is needed to show an AI assistant message to the user } public function sendUserMessageToAssistant(string $message): void { // whatever code is needed to send a message to the AI assistant } }
如您所见,当我们向AI助手告知卷函数结果时,我们充当用户向助手告知这一信息。这是因为从AI助手的视角来看,它最初确实是用户提供给AI的工具!请参阅src/AiToolBridge.php方法,了解为什么是这样的。
贡献
欢迎贡献!要贡献,请熟悉CONTRIBUTING.md。
协调披露
确保用户信息的安全和保密是我们的首要任务,我们欢迎外部安全研究者的贡献。如果您认为您在此存储库维护的软件中发现了安全漏洞,请阅读SECURITY.md以获取提交漏洞报告的说明。
版权和许可
PHP的AI工具桥由Manuel Kießling版权所有,并按照自由软件基金会发布的GNU通用公共许可证(GPL-3.0-or-later)的条款许可使用。