ai对话功能提交

This commit is contained in:
wong
2025-10-25 17:41:20 +08:00
parent a5b1861e7d
commit aa3c07a0b2
12 changed files with 1883 additions and 24 deletions

View File

@@ -15,8 +15,4 @@ Route::group('v1/ai', function () {
Route::group('doubao', function () {
Route::post('text', 'app\ai\controller\DouBaoAI@text');
});
})->middleware(['jwt']);

View File

@@ -0,0 +1,370 @@
<?php
namespace app\ai\controller;
use think\facade\Env;
use think\Controller;
class CozeAI extends Controller
{
protected $apiUrl;
protected $accessToken;
protected $headers;
/**
* 初始化
*/
public function __construct()
{
parent::__construct();
// 从环境变量获取配置
$this->apiUrl = Env::get('cozeAi.api_url');
$this->accessToken = Env::get('cozeAi.token');
if (empty($this->accessToken) || empty($this->apiUrl)) {
return json_encode(['code' => 500, 'msg' => '参数缺失']);
}
// 设置请求头
$this->headers = [
'Authorization: Bearer ' . $this->accessToken,
'Content-Type: application/json'
];
}
/**
* 创建智能体
* @param $data
* @return false|string|\think\response\Json
*/
public function createBot($data = [])
{
$space_id = Env::get('cozeAi.space_id');
$name = !empty($data['name']) ? $data['name'] : '';
$model_id = !empty($data['model_id']) ? $data['model_id'] : '';
$prompt_info = !empty($data['prompt_info']) ? $data['prompt_info'] : '';
$plugin_id_list = [
'id_list' => [
['api_id' => '7362852017859035163', 'plugin_id' => '7362852017859018779'],
['api_id' => '7472045461050851367', 'plugin_id' => '7472045461050834983'],
]
];
if (empty($name)) {
return json_encode(['code' => 500, 'msg' => '参数缺失']);
}
$model_info_config = [
'model_id' => (string)$model_id,
];
$params = [
'space_id' => $space_id,
'name' => $name,
'model_info_config' => (object)$model_info_config,
'plugin_id_list' => (object)$plugin_id_list
];
if (!empty($prompt_info)){
$new_prompt_info = [
'prompt' => $prompt_info
];
$params['prompt_info'] = (object) $new_prompt_info;
}
$result = requestCurl($this->apiUrl . '/v1/bot/create', $params, 'POST', $this->headers, 'json');
$result = json_decode($result, true);
if ($result['code'] != 0) {
return errorJson($result['msg'], $result['code']);
}
return json_encode(['code' => 200, 'msg' => '创建成功', 'data' => $result['data']]);
}
/**
* 创建智能体
* @param $data
* @return false|string|\think\response\Json
*/
public function updateBot($data = [])
{
$space_id = Env::get('cozeAi.space_id');
$bot_id = !empty($data['bot_id']) ? $data['bot_id'] : '';
$name = !empty($data['name']) ? $data['name'] : '';
$model_id = !empty($data['model_id']) ? $data['model_id'] : '';
$prompt_info = !empty($data['prompt_info']) ? $data['prompt_info'] : '';
$dataset_ids = !empty($data['dataset_ids']) ? $data['dataset_ids'] : '';
$plugin_id_list = [
'id_list' => [
['api_id' => '7362852017859035163', 'plugin_id' => '7362852017859018779'],
['api_id' => '7472045461050851367', 'plugin_id' => '7472045461050834983'],
]
];
if (empty($name) || empty($bot_id)) {
return json_encode(['code' => 500, 'msg' => '参数缺失']);
}
$model_info_config = [
'model_id' => (string)$model_id,
];
$params = [
'bot_id' => $bot_id,
'space_id' => $space_id,
'name' => $name,
'model_info_config' => (object)$model_info_config,
'plugin_id_list' => (object)$plugin_id_list
];
if (!empty($prompt_info)){
$new_prompt_info = [
'prompt' => $prompt_info
];
$params['prompt_info'] = (object) $new_prompt_info;
}
if (!empty($dataset_ids)){
$knowledge = [
'dataset_ids' => $dataset_ids
];
$params['knowledge'] = (object) $knowledge;
}
$result = requestCurl($this->apiUrl . '/v1/bot/update', $params, 'POST', $this->headers, 'json');
$result = json_decode($result, true);
if ($result['code'] != 0) {
return errorJson($result['msg'], $result['code']);
}
return json_encode(['code' => 200, 'msg' => '获取成功']);
}
/**
* 发布智能体
* @param $data
* @return false|string|\think\response\Json
*/
public function botPublish($data = [])
{
$bot_id = !empty($data['bot_id']) ? $data['bot_id'] : '';
$connector_ids = ['1024', '999'];
if (empty($bot_id) || empty($connector_ids)) {
return json_encode(['code' => 500, 'msg' => '参数缺失']);
}
$params = [
'bot_id' => $bot_id,
'connector_ids' => $connector_ids,
];
$result = requestCurl($this->apiUrl . '/v1/bot/publish', $params, 'POST', $this->headers, 'json');
$result = json_decode($result, true);
if ($result['code'] != 0) {
return errorJson($result['msg'], $result['code']);
}
return json_encode(['code' => 200, 'msg' => '发布成功']);
}
/**
* 创建知识库
* @param $data
* @return false|string|\think\response\Json
*/
public function createKnowledge($data = [])
{
$space_id = Env::get('cozeAi.space_id');
$name = !empty($data['name']) ? $data['name'] : '';
if (empty($space_id) || empty($name)) {
return json_encode(['code' => 500, 'msg' => '参数缺失']);
}
$params = [
'space_id' => $space_id,
'format_type' => 0,
'name' => $name,
];
$result = requestCurl($this->apiUrl . '/v1/datasets', $params, 'POST', $this->headers, 'json');
$result = json_decode($result, true);
if ($result['code'] != 0) {
return errorJson($result['msg'], $result['code']);
}
return json_encode(['code' => 200, 'msg' => '创建成功','data' => $result['data']]);
}
public function createDocument($data = [])
{
// 文件路径
$filePath = !empty($data['filePath']) ? $data['filePath'] : '';
$fileName = !empty($data['fileName']) ? $data['fileName'] : '';
if (empty($filePath)) {
return json_encode(['code' => 500, 'msg' => '参数缺失']);
}
// 读取文件内容
$fileContent = file_get_contents($filePath);
// 将文件内容编码为Base64
$base64EncodedContent = base64_encode($fileContent);
$dataset_id = !empty($data['dataset_id']) ? $data['dataset_id'] : '';
$document_bases = [
['name' => $fileName,'source_info' => ['file_base64' => $base64EncodedContent]]
];
$chunk_strategy = [
'chunk_type' => 0,
'remove_extra_spaces' => true
];
$params = [
'dataset_id' => (string) $dataset_id,
'document_bases' => $document_bases,
'chunk_strategy' => (object) $chunk_strategy,
'format_type' => 0
];
$headers = array_merge($this->headers, ['Agw-Js-Conv: str']);
$result = requestCurl($this->apiUrl . '/open_api/knowledge/document/create', $params, 'POST', $headers, 'json');
$result = json_decode($result, true);
if ($result['code'] != 0) {
return errorJson($result['msg'], $result['code']);
}
return json_encode(['code' => 200, 'msg' => '创建成功','data' => $result['document_infos']]);
}
/**
* 删除知识库文件
* @param $data
* @return false|string|\think\response\Json
*/
public function deleteDocument($data = [])
{
if (empty($data)) {
return json_encode(['code' => 500, 'msg' => '参数缺失']);
}
$params = [
'document_ids' => $data,
];
$headers = array_merge($this->headers, ['Agw-Js-Conv: str']);
$result = requestCurl($this->apiUrl . '/open_api/knowledge/document/delete', $params, 'POST', $headers, 'json');
$result = json_decode($result, true);
if ($result['code'] != 0) {
return errorJson($result['msg'], $result['code']);
}
return json_encode(['code' => 200, 'msg' => '删除成功']);
}
/**
* 创建会话
* @param $data
* @return false|string|\think\response\Json
*/
public function createConversation($data = [])
{
$bot_id = !empty($data['bot_id']) ? $data['bot_id'] : '';
$name = !empty($data['name']) ? $data['name'] : '';
$meta_data = !empty($data['meta_data']) ? $data['meta_data'] : [];
if (empty($bot_id) || empty($name)) {
return json_encode(['code' => 500, 'msg' => '参数缺失']);
}
$params = [
'bot_id' => $bot_id,
'name' => $name,
];
if (!empty($meta_data)){
$params['meta_data'] = $meta_data;
}
$result = requestCurl($this->apiUrl . '/v1/conversation/create', $params, 'POST', $this->headers, 'json');
$result = json_decode($result, true);
if ($result['code'] != 0) {
return errorJson($result['msg'], $result['code']);
}
return json_encode(['code' => 200, 'msg' => '创建成功','data' => $result['data']]);
}
/**
* 开始对话
* @param $data
* @return false|string|\think\response\Json
*/
public function createChat($data = [])
{
try {
$bot_id = !empty($data['bot_id']) ? $data['bot_id'] : '';
$uid = !empty($data['uid']) ? $data['uid'] : '';
$conversation_id = !empty($data['conversation_id']) ? $data['conversation_id'] : '';
$question = !empty($data['question']) ? $data['question'] : [];
if(empty($bot_id)){
return errorJson('智能体ID不能为空');
}
if(empty($conversation_id)){
return errorJson('会话ID不能为空');
}
if(empty($question)){
return errorJson('问题不能为空');
}
// 构建请求数据
$params = [
'bot_id' => strval($bot_id),
'user_id' => strval($uid),
'additional_messages' => $question,
'stream' => false,
'auto_save_history' => true
];
$url = $this->apiUrl . '/v3/chat?conversation_id='.$conversation_id;
$result = requestCurl($url, $params, 'POST', $this->headers, 'json');
$result = json_decode($result, true);
if ($result['code'] != 0) {
return errorJson($result['msg'], $result['code']);
}
return json_encode(['code' => 200, 'msg' => '发送成功','data' => $result['data']]);
} catch (\Exception $e) {
return errorJson('创建对话失败:' . $e->getMessage());
}
}
public function getConversationChat($data = [])
{
$conversation_id = !empty($data['conversation_id']) ? $data['conversation_id'] : '';
$chat_id = !empty($data['chat_id']) ? $data['chat_id'] : '';
$url = $this->apiUrl . '/v3/chat/retrieve?conversation_id='.$conversation_id.'&chat_id='.$chat_id;
$result = requestCurl($url, [], 'GET', $this->headers, 'json');
$result = json_decode($result, true);
if ($result['code'] != 0) {
return errorJson($result['msg'], $result['code']);
}
return json_encode(['code' => 200, 'msg' => '发送成功','data' => $result['data']]);
}
public function listConversationMessage($data = [])
{
$conversation_id = !empty($data['conversation_id']) ? $data['conversation_id'] : '';
$chat_id = !empty($data['chat_id']) ? $data['chat_id'] : '';
$url = $this->apiUrl . '/v3/chat/message/list?conversation_id='.$conversation_id.'&chat_id='.$chat_id;
$result = requestCurl($url, [], 'GET', $this->headers, 'json');
$result = json_decode($result, true);
if ($result['code'] != 0) {
return errorJson($result['msg'], $result['code']);
}
return json_encode(['code' => 200, 'msg' => '发送成功','data' => $result['data']]);
}
}

View File

@@ -3,7 +3,7 @@
namespace app\ai\controller;
use think\facade\Env;
class OpenAi
class OpenAI
{
protected $apiUrl;
protected $apiKey;

View File

@@ -2,37 +2,448 @@
namespace app\chukebao\controller;
use app\ai\controller\CozeAI;
use app\ai\controller\DouBaoAI;
use app\api\model\WechatFriendModel;
use app\chukebao\controller\TokensRecordController as tokensRecord;
use app\chukebao\model\AiSettings;
use app\chukebao\model\FriendSettings;
use app\chukebao\model\TokensCompany;
use library\ResponseHelper;
use think\Db;
/**
* AI聊天控制器
* 负责处理与好友的AI对话功能
*/
class AiChatController extends BaseController
{
public function index(){
// 对话状态常量
const STATUS_CREATED = 'created'; // 对话已创建
const STATUS_IN_PROGRESS = 'in_progress'; // 智能体正在处理中
const STATUS_COMPLETED = 'completed'; // 智能体已完成处理
const STATUS_FAILED = 'failed'; // 对话失败
const STATUS_REQUIRES_ACTION = 'requires_action'; // 对话中断,需要进一步处理
const STATUS_CANCELED = 'canceled'; // 对话已取消
// 轮询配置
const MAX_RETRY_TIMES = 30; // 最大重试次数
const RETRY_INTERVAL = 2; // 重试间隔(秒)
/**
* AI聊天主入口
*
* @return \think\response\Json
*/
public function index()
{
try {
// 1. 参数验证和初始化
$params = $this->validateAndInitParams();
if ($params === false) {
return ResponseHelper::error('参数验证失败');
}
// 2. 验证Tokens余额
if (!$this->checkTokensBalance($params['companyId'])) {
return ResponseHelper::error('Tokens余额不足请充值后再试');
}
// 3. 获取AI配置
$setting = $this->getAiSettings($params['companyId']);
if (!$setting) {
return ResponseHelper::error('未找到AI配置信息请先配置AI策略');
}
// 4. 获取好友AI设置
$friendSettings = $this->getFriendSettings($params['companyId'], $params['friendId']);
if (!$friendSettings) {
return ResponseHelper::error('该好友未配置或未开启AI功能');
}
// 5. 确保会话存在
$conversationId = $this->ensureConversation($friendSettings, $setting, $params);
if (!$conversationId) {
return ResponseHelper::error('创建会话失败');
}
// 6. 获取历史消息
$msgData = $this->getHistoryMessages($params['friendId'], $friendSettings);
// 7. 创建AI对话
$chatId = $this->createAiChat($setting, $friendSettings, $msgData);
if (!$chatId) {
return ResponseHelper::error('创建对话失败');
}
// 8. 等待AI处理完成轮询
$chatResult = $this->waitForChatCompletion($conversationId, $chatId);
if (!$chatResult) {
return ResponseHelper::error('AI处理超时或失败');
}
// 9. 扣除Tokens
$this->consumeTokens($chatResult, $params, $friendSettings);
// 10. 获取对话消息
$messages = $this->getChatMessages($conversationId, $chatId);
if (!$messages) {
return ResponseHelper::error('获取对话消息失败');
}
return ResponseHelper::success($messages[1]['content'], '对话成功');
} catch (\Exception $e) {
\think\facade\Log::error('AI聊天异常' . $e->getMessage());
return ResponseHelper::error('系统异常:' . $e->getMessage());
}
}
/**
* 验证和初始化参数
*
* @return array|false
*/
private function validateAndInitParams()
{
$userId = $this->getUserInfo('id');
$companyId = $this->getUserInfo('companyId');
$friendId = $this->request->param('friendId', '');
$wechatAccountId = $this->request->param('wechatAccountId', '');
$content = $this->request->param('content', '');
$friendId = $this->request->param('friendId', '');
$wechatAccountId = $this->request->param('wechatAccountId', '');
if (empty($wechatAccountId) || empty($friendId)){
if (empty($wechatAccountId) || empty($friendId)) {
return false;
}
return [
'userId' => $userId,
'companyId' => $companyId,
'friendId' => $friendId,
'wechatAccountId' => $wechatAccountId
];
}
/**
* 检查Tokens余额
*
* @param int $companyId 公司ID
* @return bool
*/
private function checkTokensBalance($companyId)
{
$tokens = TokensCompany::where(['companyId' => $companyId])->value('tokens');
return !empty($tokens) && $tokens > 1000;
}
/**
* 获取AI配置
*
* @param int $companyId 公司ID
* @return AiSettings|null
*/
private function getAiSettings($companyId)
{
return AiSettings::where(['companyId' => $companyId])->find();
}
/**
* 获取好友AI设置
*
* @param int $companyId 公司ID
* @param string $friendId 好友ID
* @return FriendSettings|null
*/
private function getFriendSettings($companyId, $friendId)
{
$friendSettings = FriendSettings::where([
'companyId' => $companyId,
'friendId' => $friendId
])->find();
if (empty($friendSettings) || $friendSettings->type == 0) {
return null;
}
return $friendSettings;
}
/**
* 确保会话存在
*
* @param FriendSettings $friendSettings 好友设置
* @param AiSettings $setting AI设置
* @param array $params 参数
* @return string|null 会话ID
*/
private function ensureConversation($friendSettings, $setting, $params)
{
if (!empty($friendSettings->conversationId)) {
return $friendSettings->conversationId;
}
// 创建新会话
$cozeAI = new CozeAI();
$data = [
'bot_id' => $setting->botId,
'name' => '与好友' . $params['friendId'] . '的对话',
'meta_data' => [
'friendId' => (string)$friendSettings->friendId,
'wechatAccountId' => (string)$params['wechatAccountId'],
],
];
$res = $cozeAI->createConversation($data);
$res = json_decode($res, true);
if ($res['code'] != 200) {
\think\facade\Log::error('创建会话失败:' . ($res['msg'] ?? '未知错误'));
return null;
}
// 保存会话ID
$conversationId = $res['data']['id'];
$friendSettings->conversationId = $conversationId;
$friendSettings->conversationTime = time();
$friendSettings->save();
return $conversationId;
}
/**
* 获取历史消息
*
* @param string $friendId 好友ID
* @param FriendSettings $friendSettings 好友设置
* @return array
*/
private function getHistoryMessages($friendId, $friendSettings)
{
$msgData = [];
// 会话创建时间小于1分钟加载最近10条消息
if ($friendSettings->conversationTime >= time() - 60) {
$messages = Db::table('s2_wechat_message')
->where('wechatFriendId', $friendId)
->where('msgType', '<', 50)
->order('wechatTime desc')
->field('id,content,msgType,isSend,wechatTime')
->limit(10)
->select();
// 按时间正序排列
usort($messages, function ($a, $b) {
return $a['wechatTime'] <=> $b['wechatTime'];
});
// 处理聊天数据
foreach ($messages as $val) {
if (empty($val['content'])) {
continue;
}
$msg = [
'role' => empty($val['isSend']) ? 'user' : 'assistant',
'content' => $val['content'],
'type' => empty($val['isSend']) ? 'question' : 'answer',
'content_type' => 'text'
];
$msgData[] = $msg;
}
} else {
// 只加载最新一条用户消息
$message = Db::table('s2_wechat_message')
->where('wechatFriendId', $friendId)
->where('msgType', '<', 50)
->where('isSend', 0)
->order('wechatTime desc')
->field('id,content,msgType,isSend,wechatTime')
->find();
if (!empty($message) && !empty($message['content'])) {
$msgData[] = [
'role' => 'user',
'content' => $message['content'],
'type' => 'question',
'content_type' => 'text'
];
}
}
return $msgData;
}
/**
* 创建AI对话
*
* @param AiSettings $setting AI设置
* @param FriendSettings $friendSettings 好友设置
* @param array $msgData 消息数据
* @return string|null 对话ID
*/
private function createAiChat($setting, $friendSettings, $msgData)
{
$cozeAI = new CozeAI();
$data = [
'bot_id' => $setting->botId,
'uid' => $friendSettings->friendId,
'conversation_id' => $friendSettings->conversationId,
'question' => $msgData,
];
$res = $cozeAI->createChat($data);
$res = json_decode($res, true);
if ($res['code'] != 200) {
\think\facade\Log::error('创建对话失败:' . ($res['msg'] ?? '未知错误'));
return null;
}
return $res['data']['id'];
}
/**
* 等待AI处理完成轮询机制
*
* @param string $conversationId 会话ID
* @param string $chatId 对话ID
* @return array|null
*/
private function waitForChatCompletion($conversationId, $chatId)
{
$cozeAI = new CozeAI();
$retryCount = 0;
while ($retryCount < self::MAX_RETRY_TIMES) {
// 获取对话状态
$res = $cozeAI->getConversationChat([
'conversation_id' => $conversationId,
'chat_id' => $chatId,
]);
$res = json_decode($res, true);
if ($res['code'] != 200) {
\think\facade\Log::error('获取对话状态失败:' . ($res['msg'] ?? '未知错误'));
return null;
}
$status = $res['data']['status'] ?? '';
// 处理不同的状态
switch ($status) {
case self::STATUS_COMPLETED:
// 对话完成,返回结果
return $res['data'];
case self::STATUS_IN_PROGRESS:
case self::STATUS_CREATED:
// 继续等待
$retryCount++;
sleep(self::RETRY_INTERVAL);
break;
case self::STATUS_FAILED:
\think\facade\Log::error('对话失败chat_id: ' . $chatId);
return null;
case self::STATUS_CANCELED:
\think\facade\Log::error('对话已取消chat_id: ' . $chatId);
return null;
case self::STATUS_REQUIRES_ACTION:
\think\facade\Log::warning('对话需要进一步处理chat_id: ' . $chatId);
return null;
default:
\think\facade\Log::error('未知状态:' . $status);
return null;
}
}
// 超时
\think\facade\Log::error('对话处理超时chat_id: ' . $chatId);
return null;
}
/**
* 扣除Tokens
*
* @param array $chatResult 对话结果
* @param array $params 参数
* @param FriendSettings $friendSettings 好友设置
*/
private function consumeTokens($chatResult, $params, $friendSettings)
{
$tokenCount = $chatResult['usage']['token_count'] ?? 0;
if (empty($tokenCount)) {
return;
}
// 获取好友昵称
$nickname = WechatFriendModel::where('id', $friendSettings->friendId)->value('nickname');
$remarks = !empty($nickname) ? '与好友【' . $nickname . '】聊天' : '与好友聊天';
// 扣除Tokens
$tokensRecord = new tokensRecord();
$data = [
'tokens' => $tokenCount * 20,
'type' => 0,
'form' => 1,
'wechatAccountId' => $params['wechatAccountId'],
'friendIdOrGroupId' => $params['friendId'],
'remarks' => $remarks,
];
$tokensRecord->consumeTokens($data);
}
/**
* 获取对话消息
*
* @param string $conversationId 会话ID
* @param string $chatId 对话ID
* @return array|null
*/
private function getChatMessages($conversationId, $chatId)
{
$cozeAI = new CozeAI();
$res = $cozeAI->listConversationMessage([
'conversation_id' => $conversationId,
'chat_id' => $chatId,
]);
$res = json_decode($res, true);
if ($res['code'] != 200) {
\think\facade\Log::error('获取对话消息失败:' . ($res['msg'] ?? '未知错误'));
return null;
}
return $res['data'] ?? [];
}
public function index2222()
{
$userId = $this->getUserInfo('id');
$companyId = $this->getUserInfo('companyId');
$friendId = $this->request->param('friendId', '');
$wechatAccountId = $this->request->param('wechatAccountId', '');
$content = $this->request->param('content', '');
if (empty($wechatAccountId) || empty($friendId)) {
return ResponseHelper::error('参数缺失');
}
$tokens = TokensCompany::where(['companyId' => $companyId])->value('tokens');
if (empty($tokens) || $tokens <= 0){
if (empty($tokens) || $tokens <= 0) {
return ResponseHelper::error('用户Tokens余额不足');
}
//读取AI配置
$setting = Db::name('ai_settings')->where(['companyId' => $companyId,'userId' => $userId])->find();
if(empty($setting)){
$setting = Db::name('ai_settings')->where(['companyId' => $companyId, 'userId' => $userId])->find();
if (empty($setting)) {
return ResponseHelper::error('未找到配置信息请先配置AI策略');
}
$config = json_decode($setting['config'],true);
$config = json_decode($setting['config'], true);
$modelSetting = $config['modelSetting'];
$round = isset($config['round']) ? $config['round'] : 10;
@@ -45,20 +456,20 @@ class AiChatController extends BaseController
->limit($round)
->select();
usort($messages, function($a, $b) {
usort($messages, function ($a, $b) {
return $a['wechatTime'] <=> $b['wechatTime'];
});
//处理聊天数据
$msg = [];
foreach ($messages as $val){
if (empty($val['content'])){
foreach ($messages as $val) {
if (empty($val['content'])) {
continue;
}
if (!empty($val['isSend'])){
$msg[] = '客服:' . $val['content'];
}else{
$msg[] = '用户:' . $val['content'];
if (!empty($val['isSend'])) {
$msg[] = '客服:' . $val['content'];
} else {
$msg[] = '用户:' . $val['content'];
}
}
$content = implode("\n", $msg);
@@ -78,13 +489,13 @@ class AiChatController extends BaseController
//AI处理
$ai = new DouBaoAI();
$res = $ai->text($params);
$res = json_decode($res,true);
$res = json_decode($res, true);
if ($res['code'] == 200) {
//扣除Tokens
$tokensRecord = new tokensRecord();
$nickname = Db::table('s2_wechat_friend')->where(['id' => $friendId])->value('nickname');
$remarks = !empty($nickname) ? '与好友【'.$nickname.'】聊天' : '与好友聊天';
$remarks = !empty($nickname) ? '与好友【' . $nickname . '】聊天' : '与好友聊天';
$data = [
'tokens' => $res['data']['token'],
'type' => 0,
@@ -95,7 +506,7 @@ class AiChatController extends BaseController
];
$tokensRecord->consumeTokens($data);
return ResponseHelper::success($res['data']['content']);
}else{
} else {
return ResponseHelper::error($res['msg']);
}

View File

@@ -0,0 +1,52 @@
<?php
namespace app\chukebao\model;
use think\Model;
/**
* AI知识库模型
*/
class AiKnowledgeBase extends Model
{
// 设置表名
protected $name = 'ai_knowledge_base';
// 设置主键
protected $pk = 'id';
// 设置JSON字段
protected $json = ['label'];
// 设置JSON字段自动转换为数组
protected $jsonAssoc = true;
/**
* 关联知识库类型
*/
public function type()
{
return $this->belongsTo(AiKnowledgeBaseType::class, 'typeId', 'id');
}
/**
* 获取有效的知识库列表(未删除)
*/
public static function getValidList($companyId, $typeId = null)
{
$where = [
['isDel', '=', 0],
['companyId', '=', $companyId]
];
if ($typeId !== null) {
$where[] = ['typeId', '=', $typeId];
}
return self::where($where)
->with(['type'])
->order('createTime', 'desc')
->select();
}
}

View File

@@ -0,0 +1,57 @@
<?php
namespace app\chukebao\model;
use think\Model;
/**
* AI知识库类型模型
*/
class AiKnowledgeBaseType extends Model
{
// 设置表名
protected $name = 'ai_knowledge_base_type';
// 设置主键
protected $pk = 'id';
// 设置JSON字段
protected $json = ['label'];
// 设置JSON字段自动转换为数组
protected $jsonAssoc = true;
// 类型常量
const TYPE_SYSTEM = 0; // 系统类型
const TYPE_USER = 1; // 用户创建类型
/**
* 获取有效的类型列表(未删除)
*/
public static function getValidList($companyId, $includeSystem = true)
{
$where = [
['isDel', '=', 0]
];
if ($includeSystem) {
$where[] = ['type|companyId', 'in', [0, $companyId]];
} else {
$where[] = ['companyId', '=', $companyId];
$where[] = ['type', '=', self::TYPE_USER];
}
return self::where($where)
->order('createTime', 'desc')
->select();
}
/**
* 检查是否为系统类型
*/
public function isSystemType()
{
return $this->type == self::TYPE_SYSTEM;
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace app\chukebao\model;
use think\Model;
class AiSettings extends Model
{
protected $pk = 'id';
protected $name = 'ai_settings';
// 自动写入时间戳
protected $autoWriteTimestamp = true;
protected $createTime = 'createTime';
protected $updateTime = 'updateTime';
}

View File

@@ -160,6 +160,26 @@ Route::group('v1/', function () {
//AI知识库
Route::group('knowledge', function () {
Route::get('init', 'app\cunkebao\controller\AiSettingsController@init');
Route::get('release', 'app\cunkebao\controller\AiSettingsController@release');
Route::get('typeList', 'app\cunkebao\controller\AiKnowledgeBaseController@typeList');
Route::get('getList', 'app\cunkebao\controller\AiKnowledgeBaseController@getList');
Route::post('add', 'app\cunkebao\controller\AiKnowledgeBaseController@add');
//Route::post('edit', 'app\cunkebao\controller\AiKnowledgeBaseController@edit');
Route::delete('delete', 'app\cunkebao\controller\AiKnowledgeBaseController@delete');
//Route::get('detail', 'app\cunkebao\controller\AiKnowledgeBaseController@detail');
Route::post('update', 'app\cunkebao\controller\AiKnowledgeBaseController@update');
Route::post('delete', 'app\cunkebao\controller\AiKnowledgeBaseController@delete');
Route::post('addType', 'app\cunkebao\controller\AiKnowledgeBaseController@addType');
Route::post('editType', 'app\cunkebao\controller\AiKnowledgeBaseController@editType');
Route::delete('deleteType', 'app\cunkebao\controller\AiKnowledgeBaseController@deleteType');
Route::get('detailType', 'app\cunkebao\controller\AiKnowledgeBaseController@detailType');
});
})->middleware(['jwt']);

View File

@@ -0,0 +1,570 @@
<?php
namespace app\cunkebao\controller;
use app\ai\controller\CozeAI;
use app\chukebao\model\AiKnowledgeBaseType;
use app\chukebao\model\AiKnowledgeBase;
use app\chukebao\model\AiSettings as AiSettingsModel;
use library\ResponseHelper;
/**
* AI知识库管理控制器
* 负责管理AI知识库类型和知识库内容
*/
class AiKnowledgeBaseController extends BaseController
{
// ==================== 知识库类型管理 ====================
/**
* 获取知识库类型列表
*
* @return \think\response\Json
*/
public function typeList()
{
try {
$companyId = $this->getUserInfo('companyId');
if (empty($companyId)) {
return ResponseHelper::error('公司信息获取失败');
}
// 获取分页参数
$page = $this->request->param('page', 1);
$pageSize = $this->request->param('pageSize', 20);
$includeSystem = $this->request->param('includeSystem', 1); // 是否包含系统类型
// 构建查询条件
$where = [['isDel', '=', 0]];
if ($includeSystem == 1) {
// 包含系统类型和本公司创建的类型
$where[] = ['type', '=', AiKnowledgeBaseType::TYPE_SYSTEM];
$where[] = ['companyId|type', 'in', [$companyId, 0]];
} else {
// 只显示本公司创建的类型
$where[] = ['companyId', '=', $companyId];
$where[] = ['type', '=', AiKnowledgeBaseType::TYPE_USER];
}
// 查询数据
$list = AiKnowledgeBaseType::where($where)
->order('type', 'asc') // 系统类型排在前面
->order('createTime', 'desc')
->paginate($pageSize, false, ['page' => $page]);
return ResponseHelper::success($list, '获取成功');
} catch (\Exception $e) {
return ResponseHelper::error('系统异常:' . $e->getMessage());
}
}
/**
* 添加知识库类型
*
* @return \think\response\Json
*/
public function addType()
{
try {
$userId = $this->getUserInfo('id');
$companyId = $this->getUserInfo('companyId');
if (empty($companyId)) {
return ResponseHelper::error('公司信息获取失败');
}
// 获取参数
$name = $this->request->param('name', '');
$description = $this->request->param('description', '');
$label = $this->request->param('label', []);
$prompt = $this->request->param('prompt', '');
// 参数验证
if (empty($name)) {
return ResponseHelper::error('类型名称不能为空');
}
// 检查名称是否重复
$exists = AiKnowledgeBaseType::where([
['companyId', '=', $companyId],
['name', '=', $name],
['isDel', '=', 0]
])->find();
if ($exists) {
return ResponseHelper::error('该类型名称已存在');
}
// 创建类型
$typeModel = new AiKnowledgeBaseType();
$data = [
'type' => AiKnowledgeBaseType::TYPE_USER,
'name' => $name,
'description' => $description,
'label' => json_decode($label,256),
'prompt' => $prompt,
'companyId' => $companyId,
'userId' => $userId,
'createTime' => time(),
'updateTime' => time(),
'isDel' => 0
];
if ($typeModel->save($data)) {
return ResponseHelper::success(['id' => $typeModel->id], '添加成功');
} else {
return ResponseHelper::error('添加失败');
}
} catch (\Exception $e) {
return ResponseHelper::error('系统异常:' . $e->getMessage());
}
}
/**
* 编辑知识库类型
*
* @return \think\response\Json
*/
public function editType()
{
try {
$companyId = $this->getUserInfo('companyId');
if (empty($companyId)) {
return ResponseHelper::error('公司信息获取失败');
}
// 获取参数
$id = $this->request->param('id', 0);
$name = $this->request->param('name', '');
$description = $this->request->param('description', '');
$label = $this->request->param('label', []);
$prompt = $this->request->param('prompt', '');
// 参数验证
if (empty($id)) {
return ResponseHelper::error('类型ID不能为空');
}
if (empty($name)) {
return ResponseHelper::error('类型名称不能为空');
}
// 查找类型
$typeModel = AiKnowledgeBaseType::where([
['id', '=', $id],
['isDel', '=', 0]
])->find();
if (!$typeModel) {
return ResponseHelper::error('类型不存在');
}
// 检查是否为系统类型
if ($typeModel->isSystemType()) {
return ResponseHelper::error('系统类型不允许编辑');
}
// 检查权限(只能编辑本公司的类型)
if ($typeModel->companyId != $companyId) {
return ResponseHelper::error('无权限编辑该类型');
}
// 检查名称是否重复(排除自己)
$exists = AiKnowledgeBaseType::where([
['companyId', '=', $companyId],
['name', '=', $name],
['id', '<>', $id],
['isDel', '=', 0]
])->find();
if ($exists) {
return ResponseHelper::error('该类型名称已存在');
}
// 更新数据
$typeModel->name = $name;
$typeModel->description = $description;
$typeModel->label = $label;
$typeModel->prompt = $prompt;
$typeModel->updateTime = time();
if ($typeModel->save()) {
return ResponseHelper::success([], '更新成功');
} else {
return ResponseHelper::error('更新失败');
}
} catch (\Exception $e) {
return ResponseHelper::error('系统异常:' . $e->getMessage());
}
}
/**
* 删除知识库类型
*
* @return \think\response\Json
*/
public function deleteType()
{
try {
$companyId = $this->getUserInfo('companyId');
if (empty($companyId)) {
return ResponseHelper::error('公司信息获取失败');
}
// 获取参数
$id = $this->request->param('id', 0);
// 参数验证
if (empty($id)) {
return ResponseHelper::error('类型ID不能为空');
}
// 查找类型
$typeModel = AiKnowledgeBaseType::where([
['id', '=', $id],
['isDel', '=', 0]
])->find();
if (!$typeModel) {
return ResponseHelper::error('类型不存在');
}
// 检查是否为系统类型
if ($typeModel->isSystemType()) {
return ResponseHelper::error('系统类型不允许删除');
}
// 检查权限(只能删除本公司的类型)
if ($typeModel->companyId != $companyId) {
return ResponseHelper::error('无权限删除该类型');
}
// 检查是否有关联的知识库
$hasKnowledge = AiKnowledgeBase::where([
['typeId', '=', $id],
['isDel', '=', 0]
])->count();
if ($hasKnowledge > 0) {
return ResponseHelper::error('该类型下存在知识库,无法删除');
}
// 软删除
$typeModel->isDel = 1;
$typeModel->delTime = time();
if ($typeModel->save()) {
return ResponseHelper::success([], '删除成功');
} else {
return ResponseHelper::error('删除失败');
}
} catch (\Exception $e) {
return ResponseHelper::error('系统异常:' . $e->getMessage());
}
}
// ==================== 知识库管理 ====================
/**
* 获取知识库列表
*
* @return \think\response\Json
*/
public function getList()
{
try {
$companyId = $this->getUserInfo('companyId');
if (empty($companyId)) {
return ResponseHelper::error('公司信息获取失败');
}
// 获取分页参数
$page = $this->request->param('page', 1);
$pageSize = $this->request->param('pageSize', 20);
$typeId = $this->request->param('typeId', 0); // 类型筛选
$keyword = $this->request->param('keyword', ''); // 关键词搜索
// 构建查询条件
$where = [
['isDel', '=', 0],
['companyId', '=', $companyId]
];
if ($typeId > 0) {
$where[] = ['typeId', '=', $typeId];
}
if (!empty($keyword)) {
$where[] = ['name', 'like', '%' . $keyword . '%'];
}
// 查询数据
$list = AiKnowledgeBase::where($where)
->with(['type'])
->order('createTime', 'desc')
->paginate($pageSize, false, ['page' => $page]);
return ResponseHelper::success($list, '获取成功');
} catch (\Exception $e) {
return ResponseHelper::error('系统异常:' . $e->getMessage());
}
}
/**
* 添加知识库
*
* @return \think\response\Json
*/
public function add()
{
try {
$userId = $this->getUserInfo('id');
$companyId = $this->getUserInfo('companyId');
if (empty($companyId)) {
return ResponseHelper::error('公司信息获取失败');
}
$datasetId = AiSettingsModel::where(['companyId' => $companyId])->value('datasetId');
// 获取参数
$typeId = $this->request->param('typeId', 0);
$name = $this->request->param('name', '');
$label = $this->request->param('label', []);
$fileUrl = $this->request->param('fileUrl', '');
// 参数验证
if (empty($typeId)) {
return ResponseHelper::error('请选择知识库类型');
}
if (empty($name)) {
return ResponseHelper::error('知识库名称不能为空');
}
if (empty($fileUrl)) {
return ResponseHelper::error('文件地址不能为空');
}
// 检查类型是否存在
$typeExists = AiKnowledgeBaseType::where([
['id', '=', $typeId],
['isDel', '=', 0]
])->find();
if (!$typeExists) {
return ResponseHelper::error('知识库类型不存在');
}
// 创建知识库
$knowledgeModel = new AiKnowledgeBase();
$data = [
'typeId' => $typeId,
'name' => $name,
'label' => json_encode($label, 256),
'fileUrl' => $fileUrl,
'companyId' => $companyId,
'userId' => $userId,
'createTime' => time(),
'updateTime' => time(),
'isDel' => 0
];
if ($knowledgeModel->save($data)) {
if (!empty($datasetId)) {
$createDocumentData = [
'filePath' => $fileUrl,
'fileName' => $name,
'dataset_id' => $datasetId
];
$cozeAI = new CozeAI();
$result = $cozeAI->createDocument($createDocumentData);
$result = json_decode($result, true);
if ($result['code'] == 200) {
$documentId = $result['data'][0]['document_id'];
AiKnowledgeBase::where('id', $knowledgeModel->id)->update(['documentId' => $documentId, 'updateTime' => time()]);
AiSettingsModel::where(['companyId' => $companyId])->update(['isRelease' => 0,'updateTime' => time()]);
}
}
return ResponseHelper::success(['id' => $knowledgeModel->id], '添加成功');
} else {
return ResponseHelper::error('添加失败');
}
} catch (\Exception $e) {
return ResponseHelper::error('系统异常:' . $e->getMessage());
}
}
/**
* 编辑知识库
*
* @return \think\response\Json
*/
public function edit()
{
try {
$companyId = $this->getUserInfo('companyId');
if (empty($companyId)) {
return ResponseHelper::error('公司信息获取失败');
}
// 获取参数
$id = $this->request->param('id', 0);
$typeId = $this->request->param('typeId', 0);
$name = $this->request->param('name', '');
$label = $this->request->param('label', []);
$fileUrl = $this->request->param('fileUrl', '');
// 参数验证
if (empty($id)) {
return ResponseHelper::error('知识库ID不能为空');
}
if (empty($typeId)) {
return ResponseHelper::error('请选择知识库类型');
}
if (empty($name)) {
return ResponseHelper::error('知识库名称不能为空');
}
// 查找知识库
$knowledgeModel = AiKnowledgeBase::where([
['id', '=', $id],
['companyId', '=', $companyId],
['isDel', '=', 0]
])->find();
if (!$knowledgeModel) {
return ResponseHelper::error('知识库不存在或无权限编辑');
}
// 检查类型是否存在
$typeExists = AiKnowledgeBaseType::where([
['id', '=', $typeId],
['isDel', '=', 0]
])->find();
if (!$typeExists) {
return ResponseHelper::error('知识库类型不存在');
}
// 更新数据
$knowledgeModel->typeId = $typeId;
$knowledgeModel->name = $name;
$knowledgeModel->label = json_encode($label, 256);
if (!empty($fileUrl)) {
$knowledgeModel->fileUrl = $fileUrl;
}
$knowledgeModel->updateTime = time();
if ($knowledgeModel->save()) {
return ResponseHelper::success([], '更新成功');
} else {
return ResponseHelper::error('更新失败');
}
} catch (\Exception $e) {
return ResponseHelper::error('系统异常:' . $e->getMessage());
}
}
/**
* 删除知识库
*
* @return \think\response\Json
*/
public function delete()
{
try {
$companyId = $this->getUserInfo('companyId');
if (empty($companyId)) {
return ResponseHelper::error('公司信息获取失败');
}
// 获取参数
$id = $this->request->param('id', 0);
// 参数验证
if (empty($id)) {
return ResponseHelper::error('知识库ID不能为空');
}
// 查找知识库
$knowledgeModel = AiKnowledgeBase::where([
['id', '=', $id],
['companyId', '=', $companyId],
['isDel', '=', 0]
])->find();
if (!$knowledgeModel) {
return ResponseHelper::error('知识库不存在或无权限删除');
}
// 软删除
$knowledgeModel->isDel = 1;
$knowledgeModel->delTime = time();
if ($knowledgeModel->save()) {
if (!empty($knowledgeModel->documentId)){
$cozeAI = new CozeAI();
$cozeAI->deleteDocument([$knowledgeModel->documentId]);
AiSettingsModel::where(['companyId' => $companyId])->update(['isRelease' => 0,'updateTime' => time()]);
}
return ResponseHelper::success([], '删除成功');
} else {
return ResponseHelper::error('删除失败');
}
} catch (\Exception $e) {
return ResponseHelper::error('系统异常:' . $e->getMessage());
}
}
/**
* 获取知识库详情
*
* @return \think\response\Json
*/
public function detail()
{
try {
$companyId = $this->getUserInfo('companyId');
if (empty($companyId)) {
return ResponseHelper::error('公司信息获取失败');
}
// 获取参数
$id = $this->request->param('id', 0);
// 参数验证
if (empty($id)) {
return ResponseHelper::error('知识库ID不能为空');
}
// 查找知识库
$knowledge = AiKnowledgeBase::where([
['id', '=', $id],
['companyId', '=', $companyId],
['isDel', '=', 0]
])->with(['type'])->find();
if (!$knowledge) {
return ResponseHelper::error('知识库不存在或无权限查看');
}
return ResponseHelper::success($knowledge, '获取成功');
} catch (\Exception $e) {
return ResponseHelper::error('系统异常:' . $e->getMessage());
}
}
}

View File

@@ -0,0 +1,344 @@
<?php
namespace app\cunkebao\controller;
use app\ai\controller\CozeAI;
use app\api\model\CompanyModel;
use app\chukebao\model\AiSettings as AiSettingsModel;
use library\ResponseHelper;
/**
* AI设置控制器
* 负责管理公司的AI智能体配置包括创建智能体、知识库等
*/
class AiSettingsController extends BaseController
{
/**
* 初始化AI设置
* 检查公司是否已有AI配置如果没有则创建默认配置
* 自动创建智能体和知识库
*
* @return \think\response\Json
*/
public function init()
{
try {
// 获取当前用户信息
$userId = $this->getUserInfo('id');
$companyId = $this->getUserInfo('companyId');
if (empty($companyId)) {
return ResponseHelper::error('公司信息获取失败');
}
// 查找公司AI设置
$settings = $this->getOrCreateAiSettings($companyId, $userId);
if (!$settings) {
return ResponseHelper::error('AI设置初始化失败');
}
// 确保智能体已创建
if (empty($settings->botId)) {
$botCreated = $this->createBot($settings);
if (!$botCreated) {
return ResponseHelper::error('智能体创建失败');
}
}
// 确保知识库已创建
if (empty($settings->datasetId)) {
$knowledgeCreated = $this->createKnowledge($settings);
if (!$knowledgeCreated) {
return ResponseHelper::error('知识库创建失败');
}
}
if (!empty($settings->botId) && !empty($settings->datasetId)) {
$cozeAI = new CozeAI();
$config = json_decode($settings->config,true);
$config['bot_id'] = $settings->botId;
$config['dataset_ids'] = [$settings->datasetId];
$cozeAI->updateBot($config);
}
// 解析配置信息
$settings->config = json_decode($settings->config, true);
return ResponseHelper::success($settings, 'AI设置初始化成功');
} catch (\Exception $e) {
return ResponseHelper::error('系统异常:' . $e->getMessage());
}
}
/**
* 获取或创建AI设置
*
* @param int $companyId 公司ID
* @param int $userId 用户ID
* @return AiSettingsModel|false
*/
private function getOrCreateAiSettings($companyId, $userId)
{
// 查找现有设置
$settings = AiSettingsModel::where(['companyId' => $companyId])->find();
if (empty($settings)) {
// 获取公司信息
$company = CompanyModel::where('id', $companyId)->find();
if (empty($company)) {
return false;
}
// 创建默认配置
$config = $this->getDefaultConfig($company['name']);
// 保存AI设置
$settings = $this->saveAiSettings($companyId, $userId, $config);
}
return $settings;
}
/**
* 获取默认AI配置
*
* @param string $companyName 公司名称
* @return array
*/
private function getDefaultConfig($companyName)
{
return [
'name' => $companyName,
'model_id' => '1737521813', // 默认模型ID
'prompt_info' => $this->getDefaultPrompt()
];
}
/**
* 获取默认提示词
*
* @return string
*/
private function getDefaultPrompt()
{
return '# 角色
你是一位全能知识客服,作为专业的客服智能体,具备全面的知识储备,能够回答用户提出的各类问题。在回答问题前,会仔细查阅知识库内容,并且始终严格遵守中国法律法规。
## 技能
### 技能 1: 回答用户问题
1. 当用户提出问题时,首先在知识库中进行搜索查找相关信息。
2. 依据知识库中的内容,为用户提供准确、清晰、完整的回答。
## 限制
- 仅依据知识库内容回答问题,对于知识库中没有的信息,如实告知用户无法回答。
- 回答必须严格遵循中国法律法规,不得出现任何违法违规内容。
- 回答需简洁明了,避免冗长复杂的表述。';
}
/**
* 保存AI设置到数据库
*
* @param int $companyId 公司ID
* @param int $userId 用户ID
* @param array $config 配置信息
* @return AiSettingsModel|false
*/
private function saveAiSettings($companyId, $userId, $config)
{
$data = [
'companyId' => $companyId,
'userId' => $userId,
'config' => json_encode($config, JSON_UNESCAPED_UNICODE),
'createTime' => time(),
'updateTime' => time(),
'botId' => 0,
'datasetId' => 0,
];
$aiSettingsModel = new AiSettingsModel();
$result = $aiSettingsModel->save($data);
if ($result) {
return AiSettingsModel::where(['companyId' => $companyId])->find();
}
return false;
}
/**
* 创建AI智能体
*
* @param AiSettingsModel $settings AI设置对象
* @return bool
*/
private function createBot($settings)
{
if (empty($settings)) {
return false;
}
try {
$config = json_decode($settings->config, true);
if (empty($config)) {
return false;
}
// 调用CozeAI创建智能体
$cozeAI = new CozeAI();
$result = $cozeAI->createBot($config);
$result = json_decode($result, true);
if ($result['code'] != 200) {
\think\facade\Log::error('智能体创建失败:' . ($result['msg'] ?? '未知错误'));
return false;
}
// 更新智能体ID
$settings->botId = $result['data']['bot_id'];
$settings->updateTime = time();
return $settings->save();
} catch (\Exception $e) {
\think\facade\Log::error('创建智能体异常:' . $e->getMessage());
return false;
}
}
/**
* 创建知识库
*
* @param AiSettingsModel $settings AI设置对象
* @return bool
*/
private function createKnowledge($settings)
{
if (empty($settings)) {
return false;
}
try {
$config = json_decode($settings->config, true);
if (empty($config)) {
return false;
}
// 调用CozeAI创建知识库
$cozeAI = new CozeAI();
$result = $cozeAI->createKnowledge(['name' => $config['name']]);
$result = json_decode($result, true);
if ($result['code'] != 200) {
\think\facade\Log::error('知识库创建失败:' . ($result['msg'] ?? '未知错误'));
return false;
}
// 更新知识库ID
$settings->datasetId = $result['data']['dataset_id'];
$settings->updateTime = time();
return $settings->save();
} catch (\Exception $e) {
\think\facade\Log::error('创建知识库异常:' . $e->getMessage());
return false;
}
}
/**
* 更新AI配置
*
* @return \think\response\Json
*/
public function updateConfig()
{
try {
$companyId = $this->getUserInfo('companyId');
if (empty($companyId)) {
return ResponseHelper::error('公司信息获取失败');
}
// 获取请求参数
$config = $this->request->param('config', []);
if (empty($config)) {
return ResponseHelper::error('配置参数不能为空');
}
// 查找现有设置
$settings = AiSettingsModel::where(['companyId' => $companyId])->find();
if (empty($settings)) {
return ResponseHelper::error('AI设置不存在请先初始化');
}
// 更新配置
$settings->config = json_encode($config, JSON_UNESCAPED_UNICODE);
$settings->updateTime = time();
if ($settings->save()) {
return ResponseHelper::success([], '配置更新成功');
} else {
return ResponseHelper::error('配置更新失败');
}
} catch (\Exception $e) {
return ResponseHelper::error('系统异常:' . $e->getMessage());
}
}
/**
* 获取AI设置详情
*
* @return \think\response\Json
*/
public function getSettings()
{
try {
$companyId = $this->getUserInfo('companyId');
if (empty($companyId)) {
return ResponseHelper::error('公司信息获取失败');
}
$settings = AiSettingsModel::where(['companyId' => $companyId])->find();
if (empty($settings)) {
return ResponseHelper::error('AI设置不存在');
}
// 解析配置信息
$settings->config = json_decode($settings->config, true);
return ResponseHelper::success($settings, '获取成功');
} catch (\Exception $e) {
return ResponseHelper::error('系统异常:' . $e->getMessage());
}
}
/**
* 发布智能体
* @return \think\response\Json
* @throws \Exception
*/
public function release()
{
$companyId = $this->getUserInfo('companyId');
$settings = AiSettingsModel::where(['companyId' => $companyId])->find();
if (!empty($settings->isRelease)) {
return ResponseHelper::success('', '已发布,无需重复发布');
}
$cozeAI = new CozeAI();
$res = $cozeAI->botPublish(['bot_id' => $settings->botId]);
$res = json_decode($res, true);
if ($res['code'] != 200) {
$msg = '发布失败失败:' . ($res['msg'] ?? '未知错误');
return ResponseHelper::error($msg);
}
$settings->isRelease = 1;
$settings->releaseTime = time();
$settings->save();
return ResponseHelper::success('', '发布成功');
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace app\cunkebao\model;
use think\Model;
class AiKnowledgeBase extends Model
{
// 设置表名
protected $name = 'ai_knowledge_base';
}

View File

@@ -0,0 +1,11 @@
<?php
namespace app\cunkebao\model;
use think\Model;
class AiKnowledgeBaseType extends Model
{
// 设置表名
protected $name = 'ai_knowledge_base_type';
}