Ver Fonte

#5406 AI Agents revamp: content structure tool

Aleksandr Trofimov há 6 meses atrás
pai
commit
855cc58d37

+ 7 - 7
inc/classes/BxDolAIQuery.php

@@ -893,22 +893,22 @@ class BxDolAIQuery extends BxDolDb
 
     public function getAgentsByAlertUnitAndAction($sUnit, $sAction, $bActiveOnly = true)
     {
-        return $this->getAll("SELECT * FROM `sys_agents_agents` WHERE `alert_unit` = :unit AND `alert_action` = :action AND `active` = :active", ['unit' => $sUnit, 'action' => $sAction, 'active' => $bActiveOnly ? 1 : 0]);
+        return $this->getAll("SELECT * FROM `sys_agents_agents` WHERE `trigger` = 'alert' AND `alert_unit` = :unit AND `alert_action` = :action AND `active` = :active", ['unit' => $sUnit, 'action' => $sAction, 'active' => $bActiveOnly ? 1 : 0]);
     }
 
     public function getAgentsByProfileId($iProfileId, $bActiveOnly = true)
     {
-        return $this->getAll("SELECT * FROM `sys_agents_agents` WHERE `profile_id` = :profile AND `active` = :active", ['profile' => $iProfileId, 'active' => $bActiveOnly ? 1 : 0]);
+        return $this->getAll("SELECT * FROM `sys_agents_agents` WHERE `trigger` = 'message' AND `profile_id` = :profile AND `active` = :active", ['profile' => $iProfileId, 'active' => $bActiveOnly ? 1 : 0]);
     }
 
-    public function getAgentsByTriggerType($sTrigger, $bActiveOnly = true)
+    public function getAgentByTriggerWebhookKey($sKey, $bActiveOnly = true)
     {
-        return $this->getAll("SELECT * FROM `sys_agents_agents` WHERE `trigger` = :trigger AND `active` = :active", ['trigger' => $sTrigger, 'active' => $bActiveOnly ? 1 : 0]);
+        return $this->getRow("SELECT * FROM `sys_agents_agents` WHERE `trigger` = 'scheduler' AND `webhook_key` = :key AND `active` = :active", ['key' => $sKey, 'active' => $bActiveOnly ? 1 : 0]);
     }
-
-    public function getAgentByTriggerWebhookKey($sKey, $bActiveOnly = true)
+    
+    public function getAgentsByTriggerType($sTrigger, $bActiveOnly = true)
     {
-        return $this->getRow("SELECT * FROM `sys_agents_agents` WHERE `webhook_key` = :key AND `active` = :active", ['key' => $sKey, 'active' => $bActiveOnly ? 1 : 0]);
+        return $this->getAll("SELECT * FROM `sys_agents_agents` WHERE `trigger` = :trigger AND `active` = :active", ['trigger' => $sTrigger, 'active' => $bActiveOnly ? 1 : 0]);
     }
 
     public function updateAgentField($iId, $sField, $sValue)

+ 110 - 0
inc/classes/BxDolAIToolContentStructure.php

@@ -0,0 +1,110 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaCore UNA Core
+ * @{
+ */
+
+use NeuronAI\Tools\PropertyType;
+use NeuronAI\Tools\Tool;
+use NeuronAI\Tools\ToolProperty;
+
+class BxDolAIToolContentStructure extends Tool
+{
+    public function __construct()
+    {
+        parent::__construct(
+            'get_content_fields',
+            'Retrieve the structure of content fields for a given module.',
+        );
+    }
+    
+    protected function properties(): array
+    {
+        return [
+            new ToolProperty(
+                name: 'module',
+                type: PropertyType::STRING,
+                description: 'The module name to retrieve content fields from. Use "system" for site accounts. Use "all" to get fields for all content modules.',
+                required: true
+            )
+        ];
+    }
+
+    public function __invoke(string $module): string
+    {        
+        $aContentModules = bx_srv('system', 'modules_list', [true], 'TemplServiceContent');
+        $s = $this->formatModulesOutputForLLM($aContentModules);
+
+        $aStructure = bx_srv('system', 'content_modules_fields', [$module], 'TemplServiceContent');
+        if (isset($aStructure['code']))
+            $s .= "\n\nError: module was not found";
+        else
+            $s .= "\n" . $this->formatStructureOutputForLLM($aStructure);
+
+        echoDbgLog($module . 's content structure: ' . $s);
+
+        return $s;
+    }
+
+    protected function formatModulesOutputForLLM(array $aContentModules): string
+    {
+        $s = "# All content modules\n\n";
+
+        foreach ($aContentModules as $sModule => $a) {
+            $s .= "- **" . $a['title'] . "** (" . $sModule . ")";
+            if ($sModule == 'system') {
+                $s .= " - system module with site accounts";
+            }
+            $s .= "\n";
+        }
+        return $s;
+    }
+
+    protected function formatStructureOutputForLLM(array $aStructure): string
+    {
+
+        $s = "# Content modules fields structure\n\n";
+
+        foreach ($aStructure as $sModule => $a) {
+            $s .= "## " . $sModule . "\n\n";
+            $s .= $a['db_table'] ? "DB table: " . $a['db_table'] . "\n" : "";
+            $s .= $a['db_table_fields'] ? "DB table fields: " . implode(', ', $a['db_table_fields']) . "\n" : "";
+            $s .= "\n";
+            $aMap = ['fields_add' => 'Fields for adding content', 'fields_edit' => 'Fields for editing content'];
+            foreach ($aMap as $sKey => $sTitle) {
+                if (isset($a[$sKey])) {
+                    $s .= "### " . $sTitle . "\n\n";
+                    foreach ($a[$sKey] as $sField => $r) {
+                        if ($r['type'] == 'custom' || $r['type'] == 'input_set')
+                            continue;
+                        $s .= "- **" . $r['name'] . "** " . (!empty($r['caption']) ? "(" . $r['caption'] . ")" : "") . (isset($r['required']) && $r['required'] ? " required" : "") . "\n";
+                        $s .= "\t- type: " . $r['type'] . "\n";
+                        if (isset($r['values']) && is_array($r['values']) && $r['type'] != 'files') {
+                            $s .= "\t- values (id:value): " . $this->formatValues($r['values']) . "\n";
+                        }
+                    }
+                }
+                $s .= "\n";
+            }
+        }
+
+        return $s;
+    }
+
+    protected function formatValues(array $aValues): string
+    {
+        $s = "";
+        foreach ($aValues as $sKey => $mixedValue) {
+            $sValue = $mixedValue;
+            if (is_array($mixedValue) && isset($mixedValue['value'])) {
+                $sValue = $mixedValue['value'];
+                $sKey = $mixedValue['key'];
+            }
+            $s .= (empty($sKey) ? 'EMPTY' : $sKey) . ":" . $sValue . ",";
+        }
+        return trim($s, ",");
+    }
+}

+ 3 - 0
inc/classes/BxDolAIToolFactory.php

@@ -41,6 +41,9 @@ class BxDolAIToolFactory extends BxDolFactory
                     pdo: BxDolDb::getInstance()->getLink(),
                 );
                 break;
+            case 'content_structure':
+                $o = BxDolAIToolContentStructure::make();
+                break;
             default:
                 bx_log('sys_agents', "Tool type {$a['type']} is not supported", BX_LOG_ERR);
                 throw new Exception("Tool type {$a['type']} is not supported");

+ 2 - 1
install/sql/system.sql

@@ -7278,7 +7278,8 @@ CREATE TABLE IF NOT EXISTS `sys_agents_tools` (
 INSERT INTO `sys_agents_tools` (`type`, `title`, `docs`, `params`, `params_user`, `duplicate`, `changed`, `active`) VALUES
 ('mysql_schema', 'MySQL Schema', 'This tool allows agents to understand the structure of the database, enabling them to construct intelligent queries without requiring you to hardcode table structures or relationships into the prompts. This tool essentially gives your agent the equivalent of a database administrator’s understanding of your schema, allowing it to craft queries that respect your data model and take advantage of existing indexes.  \r\nIt reads all tables by default, but it\'s possible to limit it to a certain number of tables by providing the list in the `tables` parameter. By limiting the schema scope, you can create specialized agents that focus on specific areas of the site.', '{\"tables\":[]}', NULL, 0, 0, 1),
 ('mysql_select', 'MySQL Select', 'Use this tool to make your agent able to run SELECT query against the database. It\'s like read-only access without ability to change anything in the DB. It works the best in par of MySQL Schema tool.  \r\nNo parameters are needed for this tool.', '{}', NULL, 0, 0, 1),
-('mysql_write', 'MySQL Write', 'Use this tool to make your agent able to performs write operations against the database (INSERT, UPDATE, DELETE). It works the best in par of MySQL Schema tool.   \r\nNo parameters are needed for this tool.  \r\n**USE WITH CAUTION**', '{}', NULL, 0, 0, 0);
+('mysql_write', 'MySQL Write', 'Use this tool to make your agent able to performs write operations against the database (INSERT, UPDATE, DELETE). It works the best in par of MySQL Schema tool.   \r\nNo parameters are needed for this tool.  \r\n**USE WITH CAUTION**', '{}', NULL, 0, 0, 0),
+('content_structure', 'Site content modules fields structure', 'This tool allows agents to understand the structure of content modules fields,  allowing them to call content adding and editing with correct data. It provide knowledge of what content modules are available and what the fields in them, event if fields are changed in fields builder.', '{}', NULL, 0, 0, 1);
 
 CREATE TABLE IF NOT EXISTS `sys_agents_chat_history` (
   `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,