diff --git a/module/zai/control.php b/module/zai/control.php index c665f8f957..e77ca44c76 100644 --- a/module/zai/control.php +++ b/module/zai/control.php @@ -195,10 +195,12 @@ class zai extends control * Ajax: 搜索知识库。 * Ajax: Search knowledge base. * + * @param string $type 'chunk'(块) | 'content'(内容) + * @param int $limit * @access public * @return void */ - public function ajaxSearchKnowledges(int $limit = 10) + public function ajaxSearchKnowledges(string $type = 'content', int $limit = 10) { if($_SERVER['REQUEST_METHOD'] !== 'POST') { @@ -215,7 +217,7 @@ class zai extends control { $key = $this->zai->getCollectionKey($collection); if(empty($key)) continue; - $searchContents = $this->zai->searchKnowledges($userPrompt, $key, $setting, $limit + 10); + $searchContents = $type === 'chunk' ? $this->zai->searchKnowledgeChunks($userPrompt, $key, $setting, $limit + 10) : $this->zai->searchKnowledges($userPrompt, $key, $setting, $limit + 10); if($searchContents) $contents = array_merge($contents, $searchContents); } diff --git a/module/zai/model.php b/module/zai/model.php index f71fe02ccf..454b71ed63 100644 --- a/module/zai/model.php +++ b/module/zai/model.php @@ -427,6 +427,32 @@ class zaiModel extends model return empty($result['data']) ? array() : $result['data']; } + /** + * 搜索知识块。 + * Search knowledge chunks. + * + * @access public + * @param string $query + * @param string $collection + * @param array $filter + * @param int $limit + * @param float $minSimilarity + * @return array + */ + public function searchKnowledgeChunks(string $query, string $collection, array $filter, int $limit = 20, float $minSimilarity = 0.8): array + { + $postData = array(); + $postData['query'] = $query; + $postData['limit'] = $limit; + $postData['min_similarity'] = $minSimilarity; + $postData['content_filter'] = $filter; + + $result = $this->callAdminAPI('/v8/memories/' . $collection . '/embeddings-search-chunks', 'POST', null, $postData); + + if($result['result'] != 'success') return array(); + return empty($result['data']) ? array() : $result['data']; + } + /** * 判断用户是否可以查看对象。 * Check if user can view object. diff --git a/module/zai/test/lib/zai.unittest.class.php b/module/zai/test/lib/zai.unittest.class.php index bf70f5a5ca..8b6442df17 100644 --- a/module/zai/test/lib/zai.unittest.class.php +++ b/module/zai/test/lib/zai.unittest.class.php @@ -394,6 +394,23 @@ class zaiTest return $result; } + /** + * Test searchKnowledgeChunks method. + * + * @param string $query + * @param string $collection + * @param array $filter + * @param int $limit + * @param float $minSimilarity + * @access public + * @return array + */ + public function searchKnowledgeChunksTest($query, $collection, $filter, $limit = 20, $minSimilarity = 0.8) + { + $result = $this->objectModel->searchKnowledgeChunks($query, $collection, $filter, $limit, $minSimilarity); + return $result; + } + /** * Test getCollectionKey method. * diff --git a/module/zai/test/model/searchknowledgechunks.php b/module/zai/test/model/searchknowledgechunks.php new file mode 100755 index 0000000000..99f59b293c --- /dev/null +++ b/module/zai/test/model/searchknowledgechunks.php @@ -0,0 +1,105 @@ +#!/usr/bin/env php +searchKnowledgeChunks(); +timeout=0 +cid=0 + +- 测试没有ZAI设置时搜索知识库块 @0 +- 测试设置ZAI配置后搜索知识库块(基本查询) @array +- 测试搜索知识库块并指定limit参数 @array +- 测试搜索知识库块并指定minSimilarity参数 @array +- 测试搜索知识库块并使用filter过滤条件 @array +- 测试搜索知识库块返回空数组(API失败) @0 +- 测试搜索知识库块使用不同的collection @array +- 测试搜索知识库块使用复杂的filter条件 @array +- 测试搜索知识库块使用空查询字符串 @array +- 测试搜索知识库块使用最小相似度0.5 @array +- 测试搜索知识库块使用最大limit值 @array +- 测试搜索知识库块使用多个filter条件 @array + +*/ +include dirname(__FILE__, 5) . '/test/lib/init.php'; +include dirname(__FILE__, 2) . '/lib/zai.unittest.class.php'; + +zenData('config')->gen(0); +zenData('user')->gen(1); + +su('admin'); + +global $tester; +$zai = new zaiTest(); + +/* 测试没有ZAI设置时搜索知识库块 */ +$result1 = $zai->searchKnowledgeChunksTest('测试查询', 'test-collection', array()); +r(empty($result1) ? 0 : count($result1)) && p() && e('0'); // 测试没有ZAI设置时搜索知识库块 + +/* 设置ZAI配置 */ +$setting = new stdClass(); +$setting->host = 'testhost.com'; +$setting->port = 8080; +$setting->appID = 'testappid123'; +$setting->token = 'testtoken123'; +$setting->adminToken = 'testadmintoken123'; +$tester->loadModel('setting')->setItem('system.zai.global.setting', json_encode($setting)); + +/* 测试设置ZAI配置后搜索知识库块(基本查询) */ +// 注意:由于没有真实的ZAI API服务器,这些测试会因为网络调用失败 +// 但我们可以验证方法的逻辑执行和参数处理 +$result2 = $zai->searchKnowledgeChunksTest('如何使用禅道', 'zentao_kb', array()); +r(is_array($result2) ? 'array' : 'not_array') && p() && e('array'); // 测试设置ZAI配置后搜索知识库块(基本查询) + +/* 测试搜索知识库块并指定limit参数 */ +$result3 = $zai->searchKnowledgeChunksTest('需求管理', 'zentao_kb', array(), 10); +r(is_array($result3) ? 'array' : 'not_array') && p() && e('array'); // 测试搜索知识库块并指定limit参数 + +/* 测试搜索知识库块并指定minSimilarity参数 */ +$result4 = $zai->searchKnowledgeChunksTest('缺陷跟踪', 'zentao_kb', array(), 20, 0.9); +r(is_array($result4) ? 'array' : 'not_array') && p() && e('array'); // 测试搜索知识库块并指定minSimilarity参数 + +/* 测试搜索知识库块并使用filter过滤条件 */ +$filter = array('objectType' => 'story'); +$result5 = $zai->searchKnowledgeChunksTest('用户故事', 'zentao_kb', $filter); +r(is_array($result5) ? 'array' : 'not_array') && p() && e('array'); // 测试搜索知识库块并使用filter过滤条件 + +/* 测试搜索知识库块返回空数组(API失败) */ +// 由于没有真实服务器,API调用会失败,应该返回空数组 +$result6 = $zai->searchKnowledgeChunksTest('测试', 'invalid_collection', array()); +r(empty($result6) ? 0 : count($result6)) && p() && e('0'); // 测试搜索知识库块返回空数组(API失败) + +/* 测试搜索知识库块使用不同的collection */ +$result7 = $zai->searchKnowledgeChunksTest('项目管理', 'project_kb', array()); +r(is_array($result7) ? 'array' : 'not_array') && p() && e('array'); // 测试搜索知识库块使用不同的collection + +/* 测试搜索知识库块使用复杂的filter条件 */ +$complexFilter = array( + 'objectType' => 'bug', + 'status' => 'active', + 'product' => 1 +); +$result8 = $zai->searchKnowledgeChunksTest('如何修复bug', 'zentao_kb', $complexFilter); +r(is_array($result8) ? 'array' : 'not_array') && p() && e('array'); // 测试搜索知识库块使用复杂的filter条件 + +/* 测试搜索知识库块使用空查询字符串 */ +$result9 = $zai->searchKnowledgeChunksTest('', 'zentao_kb', array()); +r(is_array($result9) ? 'array' : 'not_array') && p() && e('array'); // 测试搜索知识库块使用空查询字符串 + +/* 测试搜索知识库块使用最小相似度0.5 */ +$result10 = $zai->searchKnowledgeChunksTest('测试用例', 'zentao_kb', array(), 20, 0.5); +r(is_array($result10) ? 'array' : 'not_array') && p() && e('array'); // 测试搜索知识库块使用最小相似度0.5 + +/* 测试搜索知识库块使用最大limit值 */ +$result11 = $zai->searchKnowledgeChunksTest('文档管理', 'zentao_kb', array(), 100); +r(is_array($result11) ? 'array' : 'not_array') && p() && e('array'); // 测试搜索知识库块使用最大limit值 + +/* 测试搜索知识库块使用多个filter条件 */ +$multiFilter = array( + 'objectType' => 'doc', + 'product' => 1, + 'lib' => 2, + 'type' => 'text' +); +$result12 = $zai->searchKnowledgeChunksTest('API文档', 'zentao_kb', $multiFilter, 15, 0.85); +r(is_array($result12) ? 'array' : 'not_array') && p() && e('array'); // 测试搜索知识库块使用多个filter条件