PromptService.php 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. <?php
  2. namespace App\Services;
  3. use Illuminate\Support\Facades\Http;
  4. use Illuminate\Support\Facades\Log;
  5. class PromptService
  6. {
  7. protected string $baseUrl;
  8. public function __construct()
  9. {
  10. // 从配置文件读取base_url
  11. $this->baseUrl = config('services.question_bank.base_url', env('QUESTION_BANK_API_BASE', 'http://localhost:5015'));
  12. $this->baseUrl = rtrim($this->baseUrl, '/');
  13. }
  14. /**
  15. * 获取提示词列表
  16. */
  17. public function listPrompts(?string $type = null, ?string $active = null): array
  18. {
  19. try {
  20. $query = array_filter([
  21. 'type' => $type,
  22. 'active' => $active,
  23. ], fn($value) => filled($value));
  24. $response = Http::timeout(10)
  25. ->get($this->baseUrl . '/prompts', $query);
  26. if ($response->successful()) {
  27. return $response->json();
  28. }
  29. Log::warning('获取提示词列表失败', [
  30. 'status' => $response->status()
  31. ]);
  32. } catch (\Exception $e) {
  33. Log::error('获取提示词列表异常', [
  34. 'error' => $e->getMessage()
  35. ]);
  36. }
  37. return [];
  38. }
  39. /**
  40. * 保存提示词
  41. */
  42. public function savePrompt(array $data): array
  43. {
  44. try {
  45. // 先尝试更新
  46. $response = Http::timeout(10)
  47. ->put($this->baseUrl . '/prompts/default', $data);
  48. // 如果更新失败(可能不存在),则尝试创建
  49. if (!isset($response->json()['success']) || !$response->json()['success']) {
  50. $response = Http::timeout(10)
  51. ->post($this->baseUrl . '/prompts', $data);
  52. }
  53. if ($response->successful()) {
  54. return $response->json();
  55. }
  56. Log::warning('保存提示词失败', [
  57. 'status' => $response->status()
  58. ]);
  59. } catch (\Exception $e) {
  60. Log::error('保存提示词异常', [
  61. 'error' => $e->getMessage()
  62. ]);
  63. }
  64. return ['success' => false, 'message' => '保存失败'];
  65. }
  66. /**
  67. * 获取默认提示词模板
  68. */
  69. public function getDefaultPromptTemplate(): string
  70. {
  71. return '你是资深的中学数学命题专家,请为{knowledge_point}知识点生成高质量题目。
  72. 【核心要求】
  73. 1. 题目必须符合{grade_level}年级水平
  74. 2. 难度分布:基础({basic_ratio}%) + 中等({intermediate_ratio}%) + 拔高({advanced_ratio}%)
  75. 3. 题型分配:选择题({choice}道) + 填空题({fill}道) + 解答题({solution}道)
  76. 【技能覆盖】
  77. {skill_coverage}
  78. 【图示处理】
  79. - 如果原题涉及图形/示意图/坐标系/几何草图,必须在题干内内嵌一段完整的 <svg> 标签来还原图形;不要使用外链图片、base64 或占位符。
  80. - SVG 要包含明确的宽高(建议 260~360 像素),只使用基础图元(line、rect、circle、polygon、path、text),并给出必要的坐标、角点和标注文本。
  81. - 确保题干文本描述与 SVG 一致,例如“如图所示”后紧跟 SVG,且 SVG 放在题干末尾即可被前端直接渲染。
  82. 【质量标准】
  83. - 准确性:100%正确
  84. - 多样性:避免重复
  85. - 梯度性:难度递进合理
  86. - 实用性:贴近实际应用
  87. 【输出格式】
  88. {
  89. "total": {count},
  90. "questions": [
  91. {
  92. "id": "唯一标识",
  93. "stem": "题干",
  94. "answer": "标准答案",
  95. "solution": "详细解答",
  96. "difficulty": 难度值(0.3/0.6/0.85),
  97. "skill": "关联技能"
  98. }
  99. ]
  100. }';
  101. }
  102. /**
  103. * 检查服务健康状态
  104. */
  105. public function checkHealth(): bool
  106. {
  107. try {
  108. $response = Http::timeout(5)
  109. ->get($this->baseUrl . '/health');
  110. return $response->successful();
  111. } catch (\Exception $e) {
  112. Log::error('提示词服务健康检查失败', [
  113. 'error' => $e->getMessage()
  114. ]);
  115. return false;
  116. }
  117. }
  118. }