ai寻方
This commit is contained in:
41
app/Http/Controllers/Api/ai/AiController.php
Executable file
41
app/Http/Controllers/Api/ai/AiController.php
Executable file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\ai;
|
||||
|
||||
use App\BaseApp\BaseController;
|
||||
use App\Service\common\ai\xunfei\XunFeiAiService;
|
||||
use App\Service\RoleService;
|
||||
use Exception;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
|
||||
class AiController extends BaseController
|
||||
{
|
||||
//
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->insertField = ['name', 'value', 'desc'];
|
||||
$this->updateField = ['id', 'name', 'value', 'desc'];
|
||||
$this->service = XunFeiAiService::getInstance();
|
||||
}
|
||||
|
||||
public function genSingV1()
|
||||
{
|
||||
$this->insertField = ['time', 'term', 'version'];
|
||||
$param = $this->checkRequiredFields(request()->post());
|
||||
|
||||
$versionMap = [
|
||||
'fortune' => 1,
|
||||
'wellness' => 2
|
||||
];
|
||||
if (!isset($versionMap[$param['version']])) {
|
||||
return jerr('版本号错误');
|
||||
}
|
||||
return jok(
|
||||
$this->service->genSign($param['time'], $param['term'], $versionMap[$param['version']]),
|
||||
'生成成功'
|
||||
);
|
||||
}
|
||||
}
|
||||
121
app/Service/common/ai/PromptService.php
Normal file
121
app/Service/common/ai/PromptService.php
Normal file
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service\common\ai;
|
||||
|
||||
class PromptService
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* 格式化药品信息
|
||||
*/
|
||||
public function formatDrugsInfo(array $drugs): string
|
||||
{
|
||||
$drugList = [];
|
||||
foreach ($drugs as $drug) {
|
||||
$drugInfo = "{index_id: {$drug['index_id']}, 药品ID: {$drug['drug_id']}, '名称: {$drug['drug_name']}', 单价: '{$drug['price']}'}";
|
||||
// $drugInfo = "index_id: {$drug['index_id']}, 药品ID: {$drug['drug_id']}, '名称: {$drug['drug_name']}'";
|
||||
// $drugInfo = "ID:{$drug['drug_id']},名称:{$drug['drug_name']}";
|
||||
|
||||
if (!empty($drug['indications']?? '')) {
|
||||
$drugInfo .= ", 适应症: {$drug['indications']}";
|
||||
}
|
||||
|
||||
if (!empty($drug['contraindications']?? '')) {
|
||||
$drugInfo .= ", 禁忌: {$drug['contraindications']}";
|
||||
}
|
||||
|
||||
$drugList[] = $drugInfo;
|
||||
}
|
||||
|
||||
// return implode("\n", $drugList);
|
||||
return '{'. implode(",", $drugList). '}';
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化患者信息
|
||||
*/
|
||||
public function formatPatientInfo(array $userInfo): string
|
||||
{
|
||||
$info = [];
|
||||
$info[] = "年龄:" . ($userInfo['age'] ?? '未知');
|
||||
$info[] = "性别:" . ($userInfo['gender'] ?? '未知');
|
||||
$info[] = "诊断:" . ($userInfo['diagnosis'] ?? '未提供');
|
||||
|
||||
if (!empty($userInfo['medical_history'])) {
|
||||
$info[] = "患病历史:" . (is_array($userInfo['medical_history']) ?
|
||||
implode('、', $userInfo['medical_history']) : $userInfo['medical_history']);
|
||||
}
|
||||
|
||||
if (!empty($userInfo['treatment_history'])) {
|
||||
$info[] = "就诊历史:" . (is_array($userInfo['treatment_history']) ?
|
||||
implode('、', $userInfo['treatment_history']) : $userInfo['treatment_history']);
|
||||
}
|
||||
|
||||
if (!empty($userInfo['symptoms'])) {
|
||||
$info[] = "症状:" . (is_array($userInfo['symptoms']) ?
|
||||
implode('、', $userInfo['symptoms']) : $userInfo['symptoms']);
|
||||
}
|
||||
|
||||
return implode("\n", $info);
|
||||
}
|
||||
|
||||
public function genPrescriptionPrompt(array $userInfo, array $drugs): string
|
||||
{
|
||||
$patientInfo = $this->formatPatientInfo($userInfo);
|
||||
$drugsInfo = $this->formatDrugsInfo($drugs);
|
||||
|
||||
$drugsInfo = base64_encode($drugsInfo);
|
||||
$prompt = "你是一名专业的医生,请根据以下患者信息和可用药品,开具合理的处方:
|
||||
## 患者信息:
|
||||
{$patientInfo}
|
||||
## 可用药品列表(base64_encode后的):
|
||||
{$drugsInfo}
|
||||
## 请按照以下JSON格式返回处方建议:
|
||||
{
|
||||
\"ai_diagnosis\": \"AI诊断描述\",
|
||||
\"ai_advice\": \"AI医嘱\",
|
||||
\"medication_advice\": [
|
||||
{
|
||||
// \"index_id\": \"药品ID\",
|
||||
\"drug_id\": \"药品ID\",
|
||||
\"drug_name\": \"药品名称\",
|
||||
\"single_dosage\": \"单次用量\",
|
||||
}
|
||||
],
|
||||
\"frequency_description\": \"用药频次说明\",
|
||||
\"treatment_period\": \"治疗周期说明\",
|
||||
\"frequency\": \"每天次数(数字格式)\",
|
||||
\"days\": \"用药天数(数字格式)\"
|
||||
}
|
||||
## 要求:
|
||||
1. 诊断要基于患者年龄、病史和当前症状
|
||||
2. 用药建议要合理,考虑药品适应症和患者情况,只能选择我给出的药品列表中的药品
|
||||
3. 单次用量采用数字类型单位都是g
|
||||
4. 频次要合理(如:3,就是一天三次的意思)
|
||||
5. 用药天数要根据病情严重程度确定";
|
||||
|
||||
return $prompt;
|
||||
}
|
||||
|
||||
// 求签提示词封装
|
||||
public function genSignPrompt($toDay, $dayDesc = '寻常日'): string
|
||||
{
|
||||
if (empty($dayDesc)) {
|
||||
$dayDesc = '寻常日';
|
||||
}
|
||||
// toDay是日期yyyy-mm-dd
|
||||
// dayDesc是节气默认寻常日
|
||||
$prompt = "今天是{$toDay},{$dayDesc}。请模仿隐世高人,为我求签。包含【签文】(七言绝句)、【解曰】(禅意指点)。";
|
||||
return $prompt;
|
||||
}
|
||||
|
||||
// 求签提示词封装
|
||||
public function genSignPrompt2($toDay, $dayDesc = '寻常日'): string
|
||||
{
|
||||
// toDay是日期yyyy-mm-dd
|
||||
// dayDesc是节气默认寻常日
|
||||
$prompt = "今天是{$toDay},{$dayDesc}。请模仿老中医,根据这个季节和临近的节气,给出现代人的养生方。包含饮食、起居。要用一段或几段描述。切记不要使用md格式,请使用纯文本格式。并且语气要有仙风道骨的感觉";
|
||||
return $prompt;
|
||||
}
|
||||
}
|
||||
43
app/Service/common/ai/xunfei/XunFeiAiService.php
Executable file
43
app/Service/common/ai/xunfei/XunFeiAiService.php
Executable file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service\common\ai\xunfei;
|
||||
|
||||
use App\BaseApp\BaseService;
|
||||
use App\Service\common\ai\xunfei\client\XunFeiAiClientV1;
|
||||
use App\Service\common\ai\xunfei\client\XunFeiAiClientV2;
|
||||
use Exception;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class XunFeiAiService extends BaseService
|
||||
{
|
||||
protected array $optionField = ['id', 'drug_name'];
|
||||
|
||||
|
||||
private $client;
|
||||
public function __construct()
|
||||
{
|
||||
$this->isAuth = false;
|
||||
parent::__construct();
|
||||
// $this->client = XunFeiAiClientV2::getInstance();
|
||||
$this->client = XunFeiAiClientV1::getInstance();
|
||||
}
|
||||
|
||||
public function genSign(string $time, $dayDesc, $version = 1)
|
||||
{
|
||||
// 构建提示词
|
||||
$prompt = $this->client->genSignPrompt($time, $dayDesc, $version);
|
||||
// $prompt = $this->client->buildPrescriptionPrompt($userInfo, $drugModel->toArray());
|
||||
|
||||
// 发送请求(模拟)
|
||||
$requestResult = $this->client->sendRequest($prompt, 'text');
|
||||
if ($requestResult['code'] !== 0) {
|
||||
throw new Exception('AI请求失败: ' . ($requestResult['message'] ?? '未知错误'));
|
||||
}
|
||||
|
||||
// 解析响应(模拟)
|
||||
$response = $this->client->parseResponse($requestResult);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
}
|
||||
248
app/Service/common/ai/xunfei/client/XunFeiAiClientV1.php
Executable file
248
app/Service/common/ai/xunfei/client/XunFeiAiClientV1.php
Executable file
@@ -0,0 +1,248 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service\common\ai\xunfei\client;
|
||||
|
||||
use App\BaseApp\BaseClient;
|
||||
use App\Service\common\ai\PromptService;
|
||||
|
||||
class XunFeiAiClientV1 extends BaseClient
|
||||
{
|
||||
// private $appId = '0970a6eb';
|
||||
// private $apiSecret = 'MjVjZjk2ODM4NjAwOWM1MDVjZTU1MjQ2';
|
||||
// private $apiKey = '578150544693a7c2108306db2b63cdcd';
|
||||
// private $apiPassword = 'Bearer qlODxEjzXOVIIdIfyVZl:WxLxhqESNqMmOjskDVwt';
|
||||
private $apiPassword = 'Bearer nZurRXizItjgjRmPkcRu:MiJrBykLPPEqNDHsGhCl';
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
// $this->baseUrl = 'https://spark-api-open.xf-yun.com/v2/chat/completions';
|
||||
$this->baseUrl = 'https://spark-api-open.xf-yun.com/v1/chat/completions';
|
||||
$this->headers['Authorization'] = $this->apiPassword;
|
||||
$this->promptService = new PromptService();
|
||||
}
|
||||
|
||||
|
||||
public function genSignPrompt(string $time, $dayDesc, $version = 1)
|
||||
{
|
||||
if (empty($time)) {
|
||||
$time = get_time(true, 'Y-m-d');
|
||||
}
|
||||
|
||||
if ($version == 1) {
|
||||
$prompt = $this->promptService->genSignPrompt($time, $dayDesc);
|
||||
} else {
|
||||
$prompt = $this->promptService->genSignPrompt2($time, $dayDesc);
|
||||
}
|
||||
return $prompt. '\n 要求:不使用Markdown,纯文本输出,不要出现有关于Markdown的语法,分段清晰。';
|
||||
}
|
||||
|
||||
/**
|
||||
* 患者画像分析 - 构建提示词
|
||||
*/
|
||||
public function buildPatientProfilePrompt(array $userInfo, array $prescriptionHistory, string $diagnosis): string
|
||||
{
|
||||
$patientInfo = $this->formatPatientInfo($userInfo);
|
||||
$historyInfo = $this->formatPrescriptionHistory($prescriptionHistory);
|
||||
|
||||
$prompt = "你是一名医疗数据分析专家,请根据以下患者信息分析患者画像:
|
||||
|
||||
患者基本信息:
|
||||
{$patientInfo}
|
||||
|
||||
诊断信息:{$diagnosis}
|
||||
|
||||
处方历史:
|
||||
{$historyInfo}
|
||||
|
||||
请生成一个完整的患者画像分析报告,包含以下部分:
|
||||
1. 患者基本信息总结
|
||||
2. 健康状况评估
|
||||
3. 用药习惯分析
|
||||
4. 疾病风险预测
|
||||
5. 个性化医疗建议
|
||||
|
||||
请将分析结果以HTML格式返回,确保可以直接在iframe中展示。HTML结构要完整,包含必要的CSS样式。";
|
||||
|
||||
return $prompt;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户增长分析 - 构建提示词
|
||||
*/
|
||||
public function buildUserGrowthPrompt(string $type, array $growthData): string
|
||||
{
|
||||
$typeMap = [
|
||||
0 => '天',
|
||||
1 => '周',
|
||||
2 => '月',
|
||||
3 => '年'
|
||||
];
|
||||
|
||||
$periodType = $typeMap[$type] ?? '未知周期';
|
||||
$dataSummary = $this->formatGrowthData($growthData);
|
||||
|
||||
$prompt = "你是一名数据分析专家,请根据以下用户增长数据进行分析和预测:
|
||||
|
||||
统计周期:按{$periodType}统计
|
||||
增长数据:
|
||||
{$dataSummary}
|
||||
|
||||
请完成以下分析:
|
||||
1. 当前增长趋势分析(上升/下降/平稳)
|
||||
2. 增长模式识别(季节性、周期性等)
|
||||
3. 未来3个{$periodType}的用户增长预测
|
||||
4. 增长建议和优化策略
|
||||
|
||||
请将分析结果和预测以HTML格式返回,包含图表说明和趋势可视化(使用纯HTML+CSS实现简单的数据可视化),确保可以直接在iframe中展示。需要包含完整的HTML结构。";
|
||||
|
||||
return $prompt;
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化患者信息
|
||||
*/
|
||||
private function formatPatientInfo(array $userInfo): string
|
||||
{
|
||||
$info = [];
|
||||
$info[] = "年龄:" . ($userInfo['age'] ?? '未知');
|
||||
$info[] = "性别:" . ($userInfo['gender'] ?? '未知');
|
||||
$info[] = "诊断:" . ($userInfo['diagnosis'] ?? '未提供');
|
||||
|
||||
if (!empty($userInfo['medical_history'])) {
|
||||
$info[] = "患病历史:" . (is_array($userInfo['medical_history']) ?
|
||||
implode('、', $userInfo['medical_history']) : $userInfo['medical_history']);
|
||||
}
|
||||
|
||||
if (!empty($userInfo['treatment_history'])) {
|
||||
$info[] = "就诊历史:" . (is_array($userInfo['treatment_history']) ?
|
||||
implode('、', $userInfo['treatment_history']) : $userInfo['treatment_history']);
|
||||
}
|
||||
|
||||
if (!empty($userInfo['symptoms'])) {
|
||||
$info[] = "症状:" . (is_array($userInfo['symptoms']) ?
|
||||
implode('、', $userInfo['symptoms']) : $userInfo['symptoms']);
|
||||
}
|
||||
|
||||
return implode("\n", $info);
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化药品信息
|
||||
*/
|
||||
private function formatDrugsInfo(array $drugs): string
|
||||
{
|
||||
$drugList = [];
|
||||
foreach ($drugs as $drug) {
|
||||
// $drugInfo = "{index_id: {$drug['index_id']}, 药品ID: {$drug['drug_id']}, '名称: {$drug['drug_name']}', 单价: '{$drug['price']}'}";
|
||||
// $drugInfo = "index_id: {$drug['index_id']}, 药品ID: {$drug['drug_id']}, '名称: {$drug['drug_name']}'";
|
||||
$drugInfo = "ID:{$drug['drug_id']},名称:{$drug['drug_name']}";
|
||||
|
||||
if (!empty($drug['indications']?? '')) {
|
||||
$drugInfo .= ", 适应症: {$drug['indications']}";
|
||||
}
|
||||
|
||||
if (!empty($drug['contraindications']?? '')) {
|
||||
$drugInfo .= ", 禁忌: {$drug['contraindications']}";
|
||||
}
|
||||
|
||||
$drugList[] = $drugInfo;
|
||||
}
|
||||
|
||||
return implode("\n", $drugList);
|
||||
// return '{'. implode(",", $drugList). '}';
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化处方历史
|
||||
*/
|
||||
private function formatPrescriptionHistory(array $prescriptionHistory): string
|
||||
{
|
||||
if (empty($prescriptionHistory)) {
|
||||
return "无处方历史记录";
|
||||
}
|
||||
|
||||
$historyList = [];
|
||||
foreach ($prescriptionHistory as $index => $history) {
|
||||
$historyInfo = "处方" . ($index + 1) . ": ";
|
||||
$historyInfo .= "日期: " . ($history['date'] ?? '未知') . ", ";
|
||||
$historyInfo .= "诊断: " . ($history['diagnosis'] ?? '未知') . ", ";
|
||||
$historyInfo .= "药品: " . (is_array($history['drugs']) ?
|
||||
implode('、', $history['drugs']) : ($history['drugs'] ?? '无'));
|
||||
|
||||
$historyList[] = $historyInfo;
|
||||
}
|
||||
|
||||
return implode("\n", $historyList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化增长数据
|
||||
*/
|
||||
private function formatGrowthData(array $growthData): string
|
||||
{
|
||||
$dataList = [];
|
||||
foreach ($growthData as $period => $count) {
|
||||
$dataList[] = "{$period}: {$count} 用户";
|
||||
}
|
||||
|
||||
return implode("\n", $dataList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送请求到讯飞星火API(模拟实现)
|
||||
*/
|
||||
public function sendRequest(string $prompt, string $type): array
|
||||
{
|
||||
if (empty($type)) {
|
||||
$type = 'json_object';
|
||||
}
|
||||
// 这里构建实际的API请求参数
|
||||
$requestData = [
|
||||
'model' => 'lite',
|
||||
'user' => 'user_123456',
|
||||
'messages' => [
|
||||
[
|
||||
'role' => 'system',
|
||||
'content' => $prompt
|
||||
// 'content' => '你好,返回格式要用json:{id: xxxx, content: 你好}'
|
||||
]
|
||||
],
|
||||
'temperature' => 0.7,
|
||||
'response_format' => [
|
||||
'type' => $type
|
||||
],
|
||||
];
|
||||
$result = $this->init()->postJson('', $requestData);
|
||||
|
||||
if (!array_key_exists('body', $result)) {
|
||||
$this->utils->errorThrow('OldShopApi Http请求失败: '. json_encode($result));
|
||||
}
|
||||
if ($result['body']['code'] !== 0) {
|
||||
$this->utils->errorThrow('OldShopApi Http请求失败: '. $result['body']['errmsg']);
|
||||
}
|
||||
return $result['body'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析AI响应(模拟实现)
|
||||
*/
|
||||
public function parseResponse(array $apiResponse): array
|
||||
{
|
||||
// 在实际实现中,这里会解析讯飞星火的API响应
|
||||
// 替换 $apiResponse['choices'][0]['message']['content']的```json
|
||||
$content = $apiResponse['choices'][0]['message']['content'];
|
||||
// $content = str_replace('\"', '"', $content);
|
||||
// $content = str_replace(PHP_EOL, '', $content);
|
||||
// $content = str_replace(' ', '', $content);
|
||||
// $content = str_replace(' ', '', $content);
|
||||
// $content = str_replace('```json', '', $content);
|
||||
// $content = str_replace('```', '', $content);
|
||||
// $content = json_decode($content, true);
|
||||
// 现在返回模拟数据
|
||||
return [
|
||||
'success' => true,
|
||||
'data' => $content,
|
||||
'message' => '响应解析完成'
|
||||
];
|
||||
}
|
||||
}
|
||||
258
app/Service/common/ai/xunfei/client/XunFeiAiClientV2.php
Executable file
258
app/Service/common/ai/xunfei/client/XunFeiAiClientV2.php
Executable file
@@ -0,0 +1,258 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service\common\ai\xunfei\client;
|
||||
|
||||
use App\BaseApp\BaseClient;
|
||||
use App\Service\common\ai\PromptService;
|
||||
|
||||
class XunFeiAiClientV2 extends BaseClient
|
||||
{
|
||||
// private $appId = '0970a6eb';
|
||||
// private $apiSecret = 'MjVjZjk2ODM4NjAwOWM1MDVjZTU1MjQ2';
|
||||
// private $apiKey = '578150544693a7c2108306db2b63cdcd';
|
||||
private $promptService;
|
||||
private $apiPassword = 'Bearer qlODxEjzXOVIIdIfyVZl:WxLxhqESNqMmOjskDVwt';
|
||||
// private $apiPassword = 'Bearer nZurRXizItjgjRmPkcRu:MiJrBykLPPEqNDHsGhCl';
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->baseUrl = 'https://spark-api-open.xf-yun.com/v2/chat/completions';
|
||||
// $this->baseUrl = 'https://spark-api-open.xf-yun.com/v1/chat/completions';
|
||||
$this->headers['Authorization'] = $this->apiPassword;
|
||||
$this->promptService = new PromptService();
|
||||
}
|
||||
|
||||
/**
|
||||
* 开处方功能 - 构建提示词
|
||||
*/
|
||||
public function buildPrescriptionPrompt(array $userInfo, array $drugs): string
|
||||
{
|
||||
$patientInfo = $this->promptService->formatPatientInfo($userInfo);
|
||||
$drugsInfo = $this->promptService->formatDrugsInfo($drugs);
|
||||
|
||||
$prompt = "你是一名专业的医生,请根据以下患者信息和可用药品,开具合理的处方:
|
||||
## 患者信息:
|
||||
{$patientInfo}
|
||||
## 可用药品列表:
|
||||
{$drugsInfo}
|
||||
## 请按照以下JSON格式返回处方建议:
|
||||
{
|
||||
\"ai_diagnosis\": \"AI诊断描述\",
|
||||
\"ai_diagnosis\": \"AI医嘱\",
|
||||
\"medication_advice\": [
|
||||
{
|
||||
\"index_id\": \"药品ID\",
|
||||
\"drug_id\": \"药品ID\",
|
||||
\"drug_name\": \"药品名称\",
|
||||
\"single_dosage\": \"单次用量(g)\",
|
||||
}
|
||||
],
|
||||
\"frequency_description\": \"用药频次说明\",
|
||||
\"treatment_period\": \"治疗周期说明\",
|
||||
\"frequency\": \"每天次数\",
|
||||
\"days\": \"用药天数\"
|
||||
}
|
||||
## 要求:
|
||||
1. 诊断要基于患者年龄、病史和当前症状
|
||||
2. 用药建议要合理,考虑药品适应症和患者情况
|
||||
3. 单次用量要明确(如:1片、10ml等)
|
||||
4. 频次要合理(如:一天3次)
|
||||
5. 用药天数要根据病情严重程度确定";
|
||||
|
||||
return $prompt;
|
||||
}
|
||||
|
||||
/**
|
||||
* 患者画像分析 - 构建提示词
|
||||
*/
|
||||
public function buildPatientProfilePrompt(array $userInfo, array $prescriptionHistory, string $diagnosis): string
|
||||
{
|
||||
$patientInfo = $this->formatPatientInfo($userInfo);
|
||||
$historyInfo = $this->formatPrescriptionHistory($prescriptionHistory);
|
||||
|
||||
$prompt = "你是一名医疗数据分析专家,请根据以下患者信息分析患者画像:
|
||||
|
||||
患者基本信息:
|
||||
{$patientInfo}
|
||||
|
||||
诊断信息:{$diagnosis}
|
||||
|
||||
处方历史:
|
||||
{$historyInfo}
|
||||
|
||||
请生成一个完整的患者画像分析报告,包含以下部分:
|
||||
1. 患者基本信息总结
|
||||
2. 健康状况评估
|
||||
3. 用药习惯分析
|
||||
4. 疾病风险预测
|
||||
5. 个性化医疗建议
|
||||
|
||||
请将分析结果以HTML格式返回,确保可以直接在iframe中展示。HTML结构要完整,包含必要的CSS样式。";
|
||||
|
||||
return $prompt;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户增长分析 - 构建提示词
|
||||
*/
|
||||
public function buildUserGrowthPrompt(string $type, array $growthData): string
|
||||
{
|
||||
$typeMap = [
|
||||
0 => '天',
|
||||
1 => '周',
|
||||
2 => '月',
|
||||
3 => '年'
|
||||
];
|
||||
|
||||
$periodType = $typeMap[$type] ?? '未知周期';
|
||||
$dataSummary = $this->formatGrowthData($growthData);
|
||||
|
||||
$prompt = "你是一名数据分析专家,请根据以下用户增长数据进行分析和预测:
|
||||
|
||||
统计周期:按{$periodType}统计
|
||||
增长数据:
|
||||
{$dataSummary}
|
||||
|
||||
请完成以下分析:
|
||||
1. 当前增长趋势分析(上升/下降/平稳)
|
||||
2. 增长模式识别(季节性、周期性等)
|
||||
3. 未来3个{$periodType}的用户增长预测
|
||||
4. 增长建议和优化策略
|
||||
|
||||
请将分析结果和预测以HTML格式返回,包含图表说明和趋势可视化(使用纯HTML+CSS实现简单的数据可视化),确保可以直接在iframe中展示。需要包含完整的HTML结构。";
|
||||
|
||||
return $prompt;
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化患者信息
|
||||
*/
|
||||
private function formatPatientInfo(array $userInfo): string
|
||||
{
|
||||
$info = [];
|
||||
$info[] = "年龄:" . ($userInfo['age'] ?? '未知');
|
||||
$info[] = "性别:" . ($userInfo['gender'] ?? '未知');
|
||||
$info[] = "诊断:" . ($userInfo['diagnosis'] ?? '未提供');
|
||||
|
||||
if (!empty($userInfo['medical_history'])) {
|
||||
$info[] = "患病历史:" . (is_array($userInfo['medical_history']) ?
|
||||
implode('、', $userInfo['medical_history']) : $userInfo['medical_history']);
|
||||
}
|
||||
|
||||
if (!empty($userInfo['treatment_history'])) {
|
||||
$info[] = "就诊历史:" . (is_array($userInfo['treatment_history']) ?
|
||||
implode('、', $userInfo['treatment_history']) : $userInfo['treatment_history']);
|
||||
}
|
||||
|
||||
if (!empty($userInfo['symptoms'])) {
|
||||
$info[] = "症状:" . (is_array($userInfo['symptoms']) ?
|
||||
implode('、', $userInfo['symptoms']) : $userInfo['symptoms']);
|
||||
}
|
||||
|
||||
return implode("\n", $info);
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化药品信息
|
||||
*/
|
||||
private function formatDrugsInfo(array $drugs): string
|
||||
{
|
||||
$drugList = [];
|
||||
foreach ($drugs as $drug) {
|
||||
$drugInfo = "{index_id: {$drug['index_id']}, 药品ID: {$drug['drug_id']}, '名称: {$drug['drug_name']}', 单价: '{$drug['price']}'}";
|
||||
// $drugInfo = "index_id: {$drug['index_id']}, 药品ID: {$drug['drug_id']}, '名称: {$drug['drug_name']}'";
|
||||
// $drugInfo = "ID:{$drug['drug_id']},名称:{$drug['drug_name']}";
|
||||
|
||||
if (!empty($drug['indications']?? '')) {
|
||||
$drugInfo .= ", 适应症: {$drug['indications']}";
|
||||
}
|
||||
|
||||
if (!empty($drug['contraindications']?? '')) {
|
||||
$drugInfo .= ", 禁忌: {$drug['contraindications']}";
|
||||
}
|
||||
|
||||
$drugList[] = $drugInfo;
|
||||
}
|
||||
|
||||
return implode("\n", $drugList);
|
||||
// return '{'. implode(",", $drugList). '}';
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化处方历史
|
||||
*/
|
||||
private function formatPrescriptionHistory(array $prescriptionHistory): string
|
||||
{
|
||||
if (empty($prescriptionHistory)) {
|
||||
return "无处方历史记录";
|
||||
}
|
||||
|
||||
$historyList = [];
|
||||
foreach ($prescriptionHistory as $index => $history) {
|
||||
$historyInfo = "处方" . ($index + 1) . ": ";
|
||||
$historyInfo .= "日期: " . ($history['date'] ?? '未知') . ", ";
|
||||
$historyInfo .= "诊断: " . ($history['diagnosis'] ?? '未知') . ", ";
|
||||
$historyInfo .= "药品: " . (is_array($history['drugs']) ?
|
||||
implode('、', $history['drugs']) : ($history['drugs'] ?? '无'));
|
||||
|
||||
$historyList[] = $historyInfo;
|
||||
}
|
||||
|
||||
return implode("\n", $historyList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化增长数据
|
||||
*/
|
||||
private function formatGrowthData(array $growthData): string
|
||||
{
|
||||
$dataList = [];
|
||||
foreach ($growthData as $period => $count) {
|
||||
$dataList[] = "{$period}: {$count} 用户";
|
||||
}
|
||||
|
||||
return implode("\n", $dataList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送请求到讯飞星火API(模拟实现)
|
||||
*/
|
||||
public function sendRequest(string $prompt): array
|
||||
{
|
||||
// 这里构建实际的API请求参数
|
||||
$requestData = [
|
||||
'model' => 'spark-x',
|
||||
'messages' => [
|
||||
[
|
||||
'role' => 'user',
|
||||
'content' => $prompt
|
||||
]
|
||||
],
|
||||
'temperature' => 0.7,
|
||||
];
|
||||
$result = $this->init()->postJson('', $requestData);
|
||||
|
||||
ds($result);
|
||||
if (!array_key_exists('body', $result)) {
|
||||
$this->utils->errorThrow('OldShopApi Http请求失败: '. json_encode($result));
|
||||
}
|
||||
if ($result['body']['code'] !== 0) {
|
||||
$this->utils->errorThrow('OldShopApi Http请求失败: '. $result['body']['errmsg']);
|
||||
}
|
||||
return $result['body'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析AI响应(模拟实现)
|
||||
*/
|
||||
public function parseResponse(array $apiResponse): array
|
||||
{
|
||||
// 在实际实现中,这里会解析讯飞星火的API响应
|
||||
// 现在返回模拟数据
|
||||
return [
|
||||
'success' => true,
|
||||
'data' => $apiResponse,
|
||||
'message' => '响应解析完成'
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,14 @@ Route::get('/', function () {
|
||||
|
||||
Route::post('/sql/test-connection', [SqlInstallController::class, 'testConnection']);
|
||||
Route::post('/sql/start-installation', [SqlInstallController::class, 'startInstallation']);
|
||||
|
||||
///**
|
||||
// * 自动注册路由
|
||||
// */
|
||||
//UtilsService::class::getInstance()->autoRouteRegister([
|
||||
// 'ai' => \App\Http\Controllers\Api\ai\AiController::class, // ai功能暂时不用登录
|
||||
// // 不需要登录的路由生成地址
|
||||
//]);
|
||||
/*
|
||||
* -----------------------------------以下注释不要删除--------------------------------
|
||||
* 不需要登录的路由生成地址
|
||||
@@ -24,6 +32,7 @@ UtilsService::class::getInstance()->autoRouteRegister([
|
||||
'' => \App\Http\Controllers\Api\LoginController::class, // 登录控制器
|
||||
'code' => \App\Http\Controllers\core\CodeGenerationController::class, // 代码生成控制器
|
||||
// 不需要登录的路由生成地址
|
||||
'ai' => \App\Http\Controllers\Api\ai\AiController::class, // ai功能暂时不用登录
|
||||
]);
|
||||
|
||||
Route::group([], function () {
|
||||
|
||||
Reference in New Issue
Block a user