KnowledgeGraphService.php 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. <?php
  2. namespace App\Services;
  3. use Illuminate\Support\Facades\Http;
  4. use Illuminate\Support\Facades\Log;
  5. class KnowledgeGraphService
  6. {
  7. protected string $baseUrl;
  8. public function __construct()
  9. {
  10. // 从配置文件读取base_url,而不是写死
  11. $this->baseUrl = config('services.knowledge_api.base_url', env('KNOWLEDGE_API_BASE', 'http://localhost:5011'));
  12. $this->baseUrl = rtrim($this->baseUrl, '/');
  13. }
  14. /**
  15. * 获取知识点列表
  16. */
  17. public function listKnowledgePoints(int $page = 1, int $perPage = 100): array
  18. {
  19. try {
  20. $response = Http::timeout(10)
  21. ->withHeaders(['Accept' => 'application/json'])
  22. ->get($this->baseUrl . '/knowledge-points/', [
  23. 'page' => $page,
  24. 'per_page' => $perPage
  25. ]);
  26. if ($response->successful()) {
  27. $data = $response->json();
  28. $points = $data['data'] ?? $data ?? [];
  29. // 格式化知识点数据
  30. return array_map(function($kp) {
  31. return [
  32. 'id' => (string)($kp['id'] ?? $kp['kp_id'] ?? uniqid()),
  33. 'code' => $kp['kp_code'] ?? $kp['kp_id'] ?? $kp['code'] ?? 'KP_UNKNOWN',
  34. 'name' => $kp['cn_name'] ?? $kp['kp_name'] ?? $kp['name'] ?? $kp['kp_code'] ?? '未知知识点',
  35. 'subject' => $kp['category'] ?? '数学',
  36. 'phase' => $kp['phase'] ?? '',
  37. 'importance' => $kp['importance'] ?? 0,
  38. ];
  39. }, $points);
  40. }
  41. Log::warning('知识图谱API调用失败', [
  42. 'status' => $response->status(),
  43. 'url' => $this->baseUrl . '/knowledge-points',
  44. 'response' => $response->json()
  45. ]);
  46. } catch (\Exception $e) {
  47. Log::error('获取知识点列表失败', [
  48. 'error' => $e->getMessage()
  49. ]);
  50. }
  51. // 返回备用数据
  52. return $this->getFallbackKnowledgePoints();
  53. }
  54. /**
  55. * 根据知识点代码获取技能列表
  56. */
  57. public function getSkillsByKnowledgePoint(string $kpCode): array
  58. {
  59. try {
  60. $response = Http::timeout(10)
  61. ->withHeaders(['Accept' => 'application/json'])
  62. ->get($this->baseUrl . "/graph/node/{$kpCode}");
  63. if ($response->successful()) {
  64. $data = $response->json();
  65. $skills = $data['skills'] ?? [];
  66. return array_map(function($skill) {
  67. return [
  68. 'code' => $skill['skill_code'] ?? '',
  69. 'name' => $skill['skill_name'] ?? '',
  70. 'weight' => $skill['weight'] ?? 0,
  71. ];
  72. }, $skills);
  73. }
  74. Log::warning('获取技能列表失败', [
  75. 'status' => $response->status(),
  76. 'kp_code' => $kpCode
  77. ]);
  78. } catch (\Exception $e) {
  79. Log::error('获取技能列表异常', [
  80. 'kp_code' => $kpCode,
  81. 'error' => $e->getMessage()
  82. ]);
  83. }
  84. return [];
  85. }
  86. /**
  87. * 获取所有技能列表
  88. */
  89. public function listSkills(int $page = 1, int $perPage = 50): array
  90. {
  91. try {
  92. $response = Http::timeout(10)
  93. ->get($this->baseUrl . '/skills/', [
  94. 'page' => $page,
  95. 'per_page' => $perPage
  96. ]);
  97. if ($response->successful()) {
  98. $data = $response->json();
  99. $skills = $data['data'] ?? $data ?? [];
  100. // 格式化技能数据
  101. return array_map(function($skill) {
  102. return [
  103. 'id' => (string)($skill['id'] ?? $skill['skill_code'] ?? uniqid()),
  104. 'code' => $skill['skill_code'] ?? $skill['code'] ?? 'SK_UNKNOWN',
  105. 'name' => $skill['skill_name'] ?? $skill['name'] ?? $skill['skill_code'] ?? '未知技能',
  106. 'category' => $skill['skill_type'] ?? $skill['category'] ?? '基础技能'
  107. ];
  108. }, $skills);
  109. }
  110. Log::warning('技能API调用失败', [
  111. 'status' => $response->status()
  112. ]);
  113. } catch (\Exception $e) {
  114. Log::error('获取技能列表失败', [
  115. 'error' => $e->getMessage()
  116. ]);
  117. }
  118. // 返回备用数据
  119. return $this->getFallbackSkills();
  120. }
  121. /**
  122. * 检查服务健康状态
  123. */
  124. public function checkHealth(): bool
  125. {
  126. try {
  127. $response = Http::timeout(5)
  128. ->get($this->baseUrl . '/health');
  129. return $response->successful();
  130. } catch (\Exception $e) {
  131. Log::error('知识图谱服务健康检查失败', [
  132. 'error' => $e->getMessage()
  133. ]);
  134. return false;
  135. }
  136. }
  137. /**
  138. * 获取备用知识点数据
  139. */
  140. private function getFallbackKnowledgePoints(): array
  141. {
  142. return [
  143. ['id' => 'kp_1', 'code' => 'KP1001', 'name' => '因式分解基础', 'subject' => '数学', 'phase' => '初中', 'importance' => 5],
  144. ['id' => 'kp_2', 'code' => 'KP1002', 'name' => '提取公因式', 'subject' => '数学', 'phase' => '初中', 'importance' => 5],
  145. ['id' => 'kp_3', 'code' => 'KP1003', 'name' => '平方差公式', 'subject' => '数学', 'phase' => '初中', 'importance' => 5],
  146. ['id' => 'kp_4', 'code' => 'KP1004', 'name' => '完全平方公式', 'subject' => '数学', 'phase' => '初中', 'importance' => 5],
  147. ['id' => 'kp_5', 'code' => 'KP1005', 'name' => '分组分解法', 'subject' => '数学', 'phase' => '初中', 'importance' => 4],
  148. ['id' => 'kp_6', 'code' => 'KP1006', 'name' => '十字相乘法', 'subject' => '数学', 'phase' => '初中', 'importance' => 5],
  149. ['id' => 'kp_7', 'code' => 'KP1007', 'name' => '有理数运算', 'subject' => '数学', 'phase' => '初中', 'importance' => 5],
  150. ['id' => 'kp_8', 'code' => 'KP1008', 'name' => '一元二次方程', 'subject' => '数学', 'phase' => '初中', 'importance' => 5],
  151. ['id' => 'kp_9', 'code' => 'KP1009', 'name' => '不等式', 'subject' => '数学', 'phase' => '初中', 'importance' => 4],
  152. ['id' => 'kp_10', 'code' => 'KP1010', 'name' => '函数基础', 'subject' => '数学', 'phase' => '初中', 'importance' => 5],
  153. ];
  154. }
  155. /**
  156. * 获取备用技能数据
  157. */
  158. private function getFallbackSkills(): array
  159. {
  160. return [
  161. ['id' => 'sk_1', 'code' => 'SK001', 'name' => '计算能力', 'category' => '基础技能'],
  162. ['id' => 'sk_2', 'code' => 'SK002', 'name' => '逻辑推理', 'category' => '思维技能'],
  163. ['id' => 'sk_3', 'code' => 'SK003', 'name' => '模式识别', 'category' => '认知技能'],
  164. ['id' => 'sk_4', 'code' => 'SK004', 'name' => '代数运算', 'category' => '专业技能'],
  165. ['id' => 'sk_5', 'code' => 'SK005', 'name' => '解题能力', 'category' => '专业技能'],
  166. ['id' => 'sk_6', 'code' => 'SK006', 'name' => '分析能力', 'category' => '思维技能'],
  167. ['id' => 'sk_7', 'code' => 'SK007', 'name' => '抽象思维', 'category' => '高级技能'],
  168. ['id' => 'sk_8', 'code' => 'SK008', 'name' => '创新思维', 'category' => '高级技能'],
  169. ];
  170. }
  171. }