xiaoai/php_server/app/api/logic/LianLianLogic.php

1086 lines
37 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace app\api\logic;
use app\common\model\lianlian\LlChat;
use app\common\service\ConfigService;
use app\common\service\FileService;
use app\common\model\lianlian\LlScene;
use think\facade\Db;
use app\common\model\lianlian\LlAnalysis;
use app\common\model\ChatPrompt;
use app\api\logic\service\TokenLogService;
use app\common\model\user\User;
use app\common\logic\AccountLogLogic;
use app\common\enum\user\AccountLogEnum;
use think\facade\Log;
/**
* logic
*/
class LianLianLogic extends ApiLogic
{
/**
* 重试
* @param int $id
* @return bool
* @author L
* @data 2024-07-05 11:34:16
*/
public static function analysisRetry(int $id): bool
{
try {
$info = LlAnalysis::where('id', $id)->where('user_id', self::$uid)->findOrEmpty();
if ($info->isEmpty()) {
throw new \Exception("查无此信息");
}
if ($info->status != 3) {
throw new \Exception("状态错误");
}
self::analysisCron($info->task_id);
self::$returnData = $info->refresh()->toArray();
return true;
} catch (\Exception $exception) {
self::setError($exception->getMessage());
return false;
}
}
/**
* 详情
* @param int $id
* @return bool
* @author L
* @data 2024-07-05 11:34:16
*/
public static function analysisDetail(int $id): bool
{
try {
$info = LlAnalysis::where('id', $id)->where('user_id', self::$uid)->findOrEmpty();
if ($info->isEmpty()) {
throw new \Exception("查无此信息");
}
if ($info->status != 2) {
throw new \Exception("状态错误");
}
//时长 end_time - start_tim
$info->duration = $info->end_time - $info->start_time;
$info->start_time = date('Y-m-d H:i:s', $info->start_time);
$info->end_time = date('Y-m-d H:i:s', $info->end_time);
self::$returnData = $info->toArray();
return true;
} catch (\Exception $exception) {
self::setError($exception->getMessage());
return false;
}
}
/**
* 删除
* @param array $data
* @return bool
* @author L
* @data 2024-07-05 11:05:46
*/
public static function analysisDelete(array $data): bool
{
try {
if (is_string($data['id'])) {
LlAnalysis::destroy(['id' => $data['id'], 'user_id' => self::$uid]);
} else {
LlAnalysis::whereIn('id', $data['id'])->where('user_id', self::$uid)->seclect()->delete();
}
return true;
} catch (\Exception $exception) {
self::setError($exception->getMessage());
return false;
}
}
/**
* 存入草稿
* @param array $data
* @return bool
* @author Rick
* @data 2024-06-09 11:05:46
*/
public static function analysisAddDraft(array $data): bool
{
try {
LlAnalysis::update(['is_draft' => 1],['id' => $data['analysis_id']]);
self::$returnData = ['message'=>'操作成功'];
return true;
} catch (\Exception $exception) {
self::setError($exception->getMessage());
return false;
}
}
/**
* 分析工作台
* @return bool
* @author L
* @data 2024-07-05 11:05:46
*/
public static function analysisWorkbench(): bool
{
try {
// 已创建场景数
$sceneCount = LlScene::withTrashed()->where('user_id', self::$uid)->count();
// 总场景数
$totalSceneCount = LlScene::where('user_id', self::$uid)->whereOr('user_id', 0)->count();
// 已练习场景数
$practiceSceneIds = LlAnalysis::where('user_id', self::$uid)->column('distinct scene_id');
$practiceSceneCount = count($practiceSceneIds);
//待练习场景数
$pendingSceneCount = $totalSceneCount - $practiceSceneCount;
// 平均分数
$averageScore = bcadd(LlAnalysis::where('user_id', self::$uid)->avg('total_score'), 0, 2);
//最新3个场景LOGO
$sceneLogos = [];
LlScene::whereNotIn('id', $practiceSceneIds)->order('id', 'desc')->limit(3)->field('logo')->select()->each(function ($item) use (&$sceneLogos) {
$sceneLogos[] = FileService::getFileUrl($item['logo']);
});
self::$returnData = [
'scene_count' => $sceneCount,
'total_scene_count' => $totalSceneCount,
'practice_scene_count' => $practiceSceneCount,
'pending_scene_count' => $pendingSceneCount,
'average_score' => $averageScore,
'scene_logos' => $sceneLogos
];
return true;
} catch (\Exception $exception) {
self::setError($exception->getMessage());
return false;
}
}
/**
* 场景添加
* @param array $data
* @return bool
* @author L
* @data 2024-07-05 11:05:46
*/
public static function sceneAdd(array $data): bool
{
try {
//随机从配置列表中提取
$info = ConfigService::get('lianlian', 'config', []);
$data['logo'] = $info['avatars'][array_rand($info['avatars'])];
$data['coach_language'] = '中文';
$data['analysis_report_config'] = json_encode($info['directions'], JSON_UNESCAPED_UNICODE);
$data['user_id'] = self::$uid;
//
$res = LlScene::create($data)->toArray();
$data['type'] = 2;
\app\api\logic\KnowledgeLogic::bind($data, $res);
self::$returnData = $res;
return true;
} catch (\Exception $exception) {
self::setError($exception->getMessage());
return false;
}
}
/**
* 场景删除
* @param array $data
* @return bool
* @author L
* @data 2024-07-05 11:05:46
*/
public static function sceneDelete(array $data): bool
{
try {
if (is_string($data['id'])) {
LlScene::destroy(['id' => $data['id'], 'user_id' => self::$uid]);
} else {
LlScene::whereIn('id', $data['id'])->where('user_id', self::$uid)->select()->delete();
}
return true;
} catch (\Exception $exception) {
self::setError($exception->getMessage());
return false;
}
}
/**
* 场景编辑
* @param array $data
* @return bool
* @author L
* @data 2024-07-05 11:05:46
*/
public static function sceneEdit(array $data): bool
{
try {
$info = LlScene::where('id', $data['id'])->where('user_id', self::$uid)->findOrEmpty();
if ($info->isEmpty()) {
throw new \Exception("查无此信息");
}
$info->name = $data['name'] ?? $info->name;
$info->description = $data['description'] ?? $info->description;
$info->coach_name = $data['coach_name'] ?? $info->coach_name;
$info->coach_persona = $data['coach_persona'] ?? $info->coach_persona;
$info->coach_voice = $data['coach_voice'] ?? $info->coach_voice;
$info->coach_emotion = $data['coach_emotion'] ?? $info->coach_emotion;
$info->coach_intensity = $data['coach_intensity'] ?? $info->coach_intensity;
$info->practitioner_persona = $data['practitioner_persona'] ?? $info->practitioner_persona;
$info->save();
$data['type'] = 2;
\app\api\logic\KnowledgeLogic::bind($data, $info);
self::$returnData = $info->toArray();
return true;
} catch (\Exception $exception) {
self::setError($exception->getMessage());
return false;
}
}
/**
* 场景详情
* @param int $id
* @return bool
* @author L
* @data 2024-07-05 11:34:16
*/
public static function sceneDetail(int $id): bool
{
try {
$info = LlScene::findOrEmpty($id);
if ($info->isEmpty()) {
throw new \Exception("查无此信息");
}
$analysis = LlAnalysis::where([
'scene_id'=>$id,
'user_id'=>self::$uid,
'status'=>0,
'is_draft'=>1
])->findOrEmpty();
$info['is_draft'] = $analysis->isEmpty() ? 0 : 1;
$info['analysis_id'] = $analysis->id ?? 0;
$info['index_id'] = \app\common\model\knowledge\KnowledgeBind::where('data_id', $info->id)->where('type', 2)->value('index_id');
$info['knowledge'] = \app\common\model\knowledge\KnowledgeBind::alias('b')
->field('k.index_id, k.name, k.category_id, k.description, k.rerank_min_score, b.data_id, b.type')
->where('b.data_id', $id)
->join('knowledge k', 'k.index_id = b.index_id', 'LEFT')
->where('b.type', 2)
->limit(1)
->find();
if ($info->user_id != 0 && $info->user_id != self::$uid) {
throw new \Exception("查无此信息");
}
self::$returnData = $info->toArray();
return true;
} catch (\Exception $exception) {
self::setError($exception->getMessage());
return false;
}
}
/**
* 话术提炼
* @param array $data
* @return string
* @author L
* @data 2024/7/21 15:55
*/
public static function speechcraftChat(array $data): string
{
try {
$info = LlAnalysis::where('id', $data['analysis_id'])
->where('user_id', self::$uid)
->where('scene_id', $data['scene_id'])
->findOrEmpty();
if ($info->isEmpty()) {
throw new \Exception("查无此信息");
}
//不处于聊天状态
if ($info->status != 0) {
throw new \Exception("状态错误");
}
//获取场景信息
$sceneInfo = LlScene::findOrEmpty($info->scene_id);
if ($sceneInfo->isEmpty()) {
throw new \Exception("场景信息丢失");
}
//获取当前聊天
$chatInfo = LlChat::findOrEmpty($data['chat_id']);
if ($chatInfo->isEmpty()) {
throw new \Exception("聊天信息丢失");
}
//获取聊天记录
$logs = json_encode(self::chatLog($info->id, $info->scene_id, $info->user_id, $data['chat_id']), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
// 获取话术提炼关键词
$keyWords = ChatPrompt::where('id', 9)->value('prompt_text') ?? '';
if (!$keyWords) {
throw new \Exception("关键词丢失");
}
//替换数据
$keyWords = str_replace(['场景名称', '对话内容'], [$sceneInfo->name, $logs], $keyWords);
//print_r($keyWords);die;
// 检查是否挂载知识库
$bind = \app\common\model\knowledge\KnowledgeBind::where('data_id', $data['scene_id'])->where('type', 2)->limit(1)->find();
if (!empty($bind)) {
$response = self::knowledgeChat($bind, $keyWords, $sceneInfo);
}else{
//发送聊天
$response = \app\common\service\ToolsService::Ll()->chat([
'action' => 'speechcraft',
'messages' => $keyWords
]);
}
//聊天
$chatInfo->speechcraft = $response['data']['message'];
$chatInfo->save();
self::$returnData = $chatInfo->toArray();
return true;
} catch (\Exception $exception) {
self::setError($exception->getMessage());
return false;
}
}
/**
* 表现提炼
* @param array $data
* @return string
* @author L
* @data 2024/7/21 15:55
*/
public static function performanceChat(array $data): string
{
try {
$info = LlAnalysis::where('id', $data['analysis_id'])
->where('user_id', self::$uid)
->where('scene_id', $data['scene_id'])
->findOrEmpty();
if ($info->isEmpty()) {
throw new \Exception("查无此信息");
}
//不处于聊天状态
if ($info->status != 0) {
throw new \Exception("状态错误");
}
//获取场景信息
$sceneInfo = LlScene::findOrEmpty($info->scene_id);
if ($sceneInfo->isEmpty()) {
throw new \Exception("场景信息丢失");
}
//获取当前聊天
$chatInfo = LlChat::findOrEmpty($data['chat_id']);
if ($chatInfo->isEmpty()) {
throw new \Exception("聊天信息丢失");
}
$logs = self::chatLog($info->id, $info->scene_id, $info->user_id, $data['chat_id']);
if (count($logs) == 1) {
throw new \Exception("当前处于开场白,请继续对话");
}
//移除最后一条(陪练者说的)
array_pop($logs);
//获取聊天记录
$logs = json_encode($logs, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
// 获取表现提炼关键词
$keyWords = ChatPrompt::where('id', 11)->value('prompt_text') ?? '';
if (!$keyWords) {
throw new \Exception("关键词丢失");
}
//替换方向
$keyWords = str_replace(['方向1', '方向2', '方向3', '方向4', '方向5'], $sceneInfo->analysis_report_config, $keyWords);
//替换数据
$keyWords = str_replace(['场景名称', '对话内容'], [$sceneInfo->name, $logs], $keyWords);
// 检查是否挂载知识库
$bind = \app\common\model\knowledge\KnowledgeBind::where('data_id', $data['scene_id'])->where('type', 2)->limit(1)->find();
if (!empty($bind)) {
$response = self::knowledgeChat($bind, $keyWords, $sceneInfo);
}else{
//发送聊天
$response = \app\common\service\ToolsService::Ll()->chat([
'action' => 'performance',
'messages' => $keyWords
]);
}
//聊天
$chatInfo->performance = $response['data']['message'];
$chatInfo->save();
self::$returnData = $chatInfo->toArray();
return true;
} catch (\Exception $exception) {
self::setError($exception->getMessage());
return false;
}
}
/**
* 开始聊天
* @param array $data
* @param int $userId
* @return bool
* @throws \Exception
* @author L
* @data 2024/7/9 16:15
*/
public static function startChat(array $data): bool
{
Db::startTrans();
//计费,改为结算的时候扣费
// $unit = TokenLogService::checkToken(self::$uid, 'lianlian');
try {
// 场景ID
if (!isset($data['scene_id'])) {
throw new \Exception('场景ID不能为空');
}
$info = LlScene::findOrEmpty($data['scene_id']);
if ($info->isEmpty()) {
throw new \Exception("查无此信息");
}
if ($info->user_id != 0 && $info->user_id != self::$uid) {
throw new \Exception("查无此信息");
}
//场景重练或发起新对话时,删除无效的旧对话数据
$drafts = LlAnalysis::where([
'scene_id' => $data['scene_id'],
'user_id' => self::$uid,
'is_draft' => 1,
'status' => 0
])->select()->toArray();
if ($drafts){
foreach ($drafts as $draft){
LlChat::destroy(['analysis_id'=>$draft['id']]);
LlAnalysis::destroy($draft['id']);
// Log::write('场景ID'.$data['scene_id'].'对话ID'.$draft['id'].'删除成功');
}
}
$task_id = generate_unique_task_id();
//新增分析
$analysisInfo = LlAnalysis::create([
'scene_id' => $data['scene_id'],
'user_id' => self::$uid,
'task_id' => $task_id,
'start_time' => time(),
]);
// 获取开场白
$keyWords = ChatPrompt::where('id', 6)->value('prompt_text') ?? '';
if (!$keyWords) {
throw new \Exception("关键词丢失");
}
//替换数据
$keyWords = str_replace(['陪练画像描述', '陪练母语', '练习者扮演的人设', '练习场景'], [$info->coach_persona, $info->coach_language, $info->practitioner_persona, $info->description], $keyWords);
// 检查是否挂载知识库
$bind = \app\common\model\knowledge\KnowledgeBind::where('data_id', $data['scene_id'])->where('type', 2)->limit(1)->find();
if (!empty($bind)) {
$response = self::knowledgeChat($bind, $keyWords, $info);
}else{
// 发起聊天
$response = \app\common\service\ToolsService::Ll()->chat([
'action' => 'start',
'voice' => $info->coach_voice,
'emotion' => $info->coach_emotion,
'intensity' => $info->coach_intensity,
'messages' => [
[
'role' => 'user',
'content' => $keyWords
]
],
]);
}
if (!isset($response['data'])) {
throw new \Exception("发起场景陪练失败");
}
//保存数据
$chatInfo = LlChat::create([
'scene_id' => $analysisInfo->scene_id,
'user_id' => $analysisInfo->user_id,
'analysis_id' => $analysisInfo->id,
'preliminary_ask' => $response['data']['message'] ?? '',
'preliminary_ask_audio' => FileService::downloadFileBySource($response['data']['audio_url'], 'audio'),
'preliminary_ask_audio_duration' => $response['data']['audio_duration'] ?? 0,
]);
//token扣除改为结算时扣费
// User::userTokensChange($analysisInfo->user_id, $unit);
//记录日志,改为结算时扣费
// AccountLogLogic::recordUserTokensLog(true, $analysisInfo->user_id, AccountLogEnum::TOKENS_DEC_AI_LIANLIAN, $unit, $analysisInfo->task_id);
self::$returnData = $chatInfo->toArray();
Db::commit();
return true;
} catch (\Exception $e) {
Db::rollback();
self::setError($e->getMessage());
return false;
}
}
private static function flattenArray($array) {
$result = [];
foreach ($array as $value) {
if (is_array($value)) {
$result = array_merge($result, self::flattenArray($value));
} else {
$result[] = $value;
}
}
return $result;
}
private static function knowledgeChat($bind, $keyWords, $info){
$knowledge = \app\common\model\knowledge\Knowledge::where('id', $bind['kid'])->limit(1)->find();
if (empty($knowledge)) {
throw new \Exception("挂载的知识库不存在");
}
//clogger($keyWords, 'll');
$knResponse = \app\api\logic\KnowledgeLogic::ladderPlayerChat([
'message' => $keyWords,
'indexid' => $knowledge['index_id'],
'rerank_min_score' => $knowledge['rerank_min_score'] ?? 0.2,
'stream' => false,
'user_id' => self::$uid,
'scene' => '陪练聊天',
'voice' => $info->coach_voice,
'emotion' => $info->coach_emotion,
'intensity' => $info->coach_intensity,
]);
$response['data'] = array(
'message' => $knResponse['choices'][0]['message']['content']?? '',
'audio_url' => $knResponse['audio_url'] ?? '',
'audio_duration' => $knResponse['audio_duration'] ?? 0,
);
return $response;
}
/**
* 继续聊天
* @param array $data
* @param int $userId
* @return bool
* @throws \Exception
* @author L
* @data 2024/7/9 16:15
*/
public static function continueChat(array $data): bool
{
Db::startTrans();
try {
$info = LlAnalysis::where('is_draft', 1)
->where('id', $data['analysis_id'])
->where('user_id', self::$uid)
->where('scene_id', $data['scene_id'])
->order('id','DESC')
->findOrEmpty();
if ($info->isEmpty()) {
throw new \Exception("查无此信息");
}
//不处于聊天状态
if ($info->status != 0) {
throw new \Exception("状态错误");
}
//获取场景信息
$sceneInfo = LlScene::findOrEmpty($info->scene_id);
if ($sceneInfo->isEmpty()) {
throw new \Exception("场景信息丢失");
}
//保存数据
$chatInfo = LlChat::create([
'scene_id' => $info->scene_id,
'user_id' => $info->user_id,
'analysis_id' => $info->id,
'ask' => $data['ask'],
'ask_audio' => FileService::setFileUrl($data['ask_audio']),
'ask_audio_duration' => $data['ask_audio_duration'],
]);
//获取聊天记录
$logs = json_encode(self::chatLog($info->id, $info->scene_id, self::$uid), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
// 对话延续关键词
$keyWords = ChatPrompt::where('id', 10)->value('prompt_text') ?? '';
if (!$keyWords) {
throw new \Exception("关键词丢失");
}
//替换数据
$keyWords = str_replace(['场景名称', '对话内容', '陪练母语'], [$sceneInfo->name, $logs, $sceneInfo->coach_language], $keyWords);
// 检查是否挂载知识库
$bind = \app\common\model\knowledge\KnowledgeBind::where('data_id', $data['scene_id'])->where('type', 2)->limit(1)->find();
if (!empty($bind)) {
$response = self::knowledgeChat($bind, $keyWords, $sceneInfo);
}else{
// 发起聊天
$response = \app\common\service\ToolsService::Ll()->chat([
'action' => 'continue',
'voice' => $sceneInfo->coach_voice,
'emotion' => $sceneInfo->coach_emotion,
'intensity' => $sceneInfo->coach_intensity,
'messages' => [
[
'role' => 'user',
'content' => $keyWords
]
],
]);
}
if (!isset($response['data'])) {
throw new \Exception("陪练对话失败");
}
$chatInfo->reply = $response['data']['message'];
$chatInfo->reply_audio = FileService::downloadFileBySource($response['data']['audio_url'], 'audio');
$chatInfo->reply_audio_duration = $response['data']['audio_duration'];
$chatInfo->save();
self::$returnData = $chatInfo->toArray();
Db::commit();
return true;
} catch (\Exception $e) {
Db::rollback();
self::setError($e->getMessage());
return false;
}
}
/**
* 继续聊天
* @param string $audio
* @param int $userId
* @return bool
* @throws \Exception
* @author L
* @data 2024/7/9 16:15
*/
public static function chatSTT(string $audio): bool
{
try {
// 发起聊天
$response = \app\common\service\ToolsService::Ll()->stt([
'audio_url' => $audio,
]);
if (!isset($response['data'])) {
throw new \Exception("语音识别失败");
}
self::$returnData = ['message' => $response['data']['message'], 'audio_duration' => $response['data']['audio_duration']];
return true;
} catch (\Exception $e) {
self::setError($e->getMessage());
return false;
}
}
/**
* 获取聊天记录
* @param int $analysisId
* @param int $sceneId
* @param int $userId
* @return array
*/
public static function chatLog(int $analysisId, int $sceneId, int $userId, int $chatId = 0): array
{
// 获取开场白
$keyWords = ChatPrompt::where('id', 6)->value('prompt_text') ?? '';
if (!$keyWords) {
throw new \Exception("关键词丢失");
}
$logs = [];
LlChat::where('analysis_id', $analysisId)
->where('scene_id', $sceneId)
->where('user_id', $userId)
->when($chatId != 0, function ($query) use ($chatId) {
$query->where('id', '<=', $chatId);
})
->order('id', 'asc')
->select()
->each(function ($item, $key) use (&$logs, $keyWords) {
if ($key == 0) {
// 获取助理提示词
$info = LlScene::field(['coach_persona', 'coach_language', 'practitioner_persona', 'description'])->findOrEmpty($item['scene_id']);
//替换数据
$keyWords = str_replace(['陪练画像描述', '陪练母语', '练习者扮演的人设', '练习场景'], [$info->coach_persona, $info->coach_language, $info->practitioner_persona, $info->description], $keyWords);
$logs[] = [
'role' => 'user',
'content' => $keyWords
];
$logs[] = [
'role' => 'assistant',
'content' => $item->preliminary_ask
];
} else {
$logs[] = [
'role' => 'user',
'content' => $item->ask
];
if (!empty($item->reply)) {
$logs[] = [
'role' => 'assistant',
'content' => $item->reply
];
}
}
});
return $logs;
}
/**
* 结束聊天
* @param array $data
* @return bool
* @author L
* @data 2024/7/11 9:47
*/
public static function endChat(array $data): bool
{
try {
//计费,改为结算的时候扣费
$unit = TokenLogService::checkToken(self::$uid, 'lianlian');
$info = LlAnalysis::where('id', $data['analysis_id'])
->where('user_id', self::$uid)
->where('scene_id', $data['scene_id'])
->findOrEmpty();
if ($info->isEmpty()) {
throw new \Exception("查无此信息");
}
//不处于聊天状态
if ($info->status != 0) {
throw new \Exception("状态错误");
}
//陪练结束,中台扣费
$response = \app\common\service\ToolsService::Ll()->chat([
'action' => 'end',
]);
if (!isset($response['data'])) {
throw new \Exception("陪练结束失败");
}
$info->status = 1;
$info->is_draft = 0;
$info->end_time = time();
$info->save();
self::$returnData = $info->toArray();
//token扣除
User::userTokensChange($info->user_id, $unit);
//记录日志
AccountLogLogic::recordUserTokensLog(true, $info->user_id, AccountLogEnum::TOKENS_DEC_AI_LIANLIAN, $unit, $info->task_id);
return true;
} catch (\Exception $exception) {
self::setError($exception->getMessage());
return false;
}
}
/**
* @desc 视频定时任务
* @return bool|void
* @date 2024/10/2 10:36
* @throws \GuzzleHttp\Exception\GuzzleException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author dagouzi
*/
public static function analysisCron(string $taskId = '')
{
ini_set('memory_limit', '-1');
ini_set('max_execution_time', 0);
try {
if ($taskId == '') {
//请求12小时内还处于分析中状态的任务
LlAnalysis::where('status', 1)
->where('create_time', '<=', strtotime('-12 hours'))
->select()
->each(function ($item) {
$item->status = 3;
$item->remark = '执行超时';
$item->save();
});
}
// 第一步:获取任务列表
$taskModel = LlAnalysis::where('tries', '<', 3)
->order('id', 'asc')
->limit(3);
if ($taskId) {
$taskModel = $taskModel->where('task_id', $taskId)->where('status', 3);
} else {
$taskModel = $taskModel->where('status', 1);
}
//第二步遍历任务
$taskModel->select()->each(function ($item) {
//如果存在失败且还没到执行时间1分钟后执行
if ($item->tries >= 1 && strtotime($item->update_time) > strtotime('-1 minute')) {
return true;
}
try {
$tries = $item->tries;
//分析模块
//获取场景信息
$sceneInfo = LlScene::findOrEmpty($item->scene_id);
if ($sceneInfo->isEmpty()) {
$item->status = 3;
$item->remark = '场景信息丢失';
$item->save();
return true;
}
//获取聊天记录
$logs = self::chatLog($item->id, $item->scene_id, $item->user_id);
if (!$logs) {
$item->status = 3;
$item->remark = '聊天记录丢失';
$item->save();
return true;
}
$logs = json_encode($logs, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
if (!$item->model_response) {
// 获取模块分析关键词
$keyWords = ChatPrompt::where('id', 8)->value('prompt_text') ?? '';
if (!$keyWords) {
$item->status = 3;
$item->remark = '模块分析关键词丢失';
$item->save();
return true;
}
//替换方向
$keyWords = str_replace(['方向1', '方向2', '方向3', '方向4', '方向5'], $sceneInfo->analysis_report_config, $keyWords);
//替换数据
$keyWords = str_replace(['场景名称', '对话内容'], [$sceneInfo->name, $logs], $keyWords);
// 发起聊天
$response = \app\common\service\ToolsService::Ll()->chat([
'action' => 'analysis',
'messages' => [
[
'role' => 'user',
'content' => $keyWords
]
],
]);
if (!isset($response['data'])) {
if ($item->tries >= 3) {
$item->status = 3;
$item->remark = '模块分析失败';
$item->save();
return true;
}
$item->tries = $item->tries + 1;
$item->save();
return true;
}
//总分数
$totalScore = array_sum(array_column($response['data']['message'], 'score'));
$item->model_response = json_encode($response['data']['message'], JSON_UNESCAPED_UNICODE);
$item->total_score = $totalScore;
$item->save();
}
//总分析
if (!$item->total_response) {
// 获取总体分析关键词
$keyWords = ChatPrompt::where('id', 7)->value('prompt_text') ?? '';
if (!$keyWords) {
$item->status = 3;
$item->remark = '总体分析关键词丢失';
$item->save();
return true;
}
//替换方向
$keyWords = str_replace(['方向1', '方向2', '方向3', '方向4', '方向5'], $sceneInfo->analysis_report_config, $keyWords);
//替换数据
$keyWords = str_replace(['场景名称', '对话内容'], [$sceneInfo->name, $logs], $keyWords);
// 发起聊天
$response = \app\common\service\ToolsService::Ll()->chat([
'action' => 'analysis',
'messages' => [
[
'role' => 'user',
'content' => $keyWords
]
],
]);
if (!isset($response['data'])) {
if ($item->tries >= 3) {
$item->status = 3;
$item->remark = '总体分析失败';
$item->save();
return true;
}
$item->tries = $item->tries + 1;
$item->save();
return true;
}
$item->total_response = $response['data']['message'];
$item->save();
}
$item->status = 2;
$item->remark = '分析完成';
$item->save();
return true;
} catch (\think\exception\HttpResponseException $e) {
$item->tries = $tries + 1;
$item->save();
self::setError($e->getResponse()->getData()['msg'] ?? '提交任务出错');
return true;
}
});
} catch (\Exception $e) {
//TODO
self::setError($e->getMessage());
return false;
}
return true;
}
}