259 lines
9.3 KiB
PHP
Executable File
259 lines
9.3 KiB
PHP
Executable File
<?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' => '响应解析完成'
|
||
];
|
||
}
|
||
}
|