AiKnowledgeService.php 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. <?php
  2. namespace App\Services;
  3. use App\Models\KnowledgePoint;
  4. use Illuminate\Support\Facades\Cache;
  5. class AiKnowledgeService
  6. {
  7. public function matchKnowledgePoints(string $questionText, array $candidates = []): array
  8. {
  9. $matched = [];
  10. $pool = $candidates;
  11. if (empty($pool)) {
  12. $pool = KnowledgePoint::query()->select(['kp_code', 'name'])->limit(200)->get()->toArray();
  13. }
  14. foreach ($pool as $item) {
  15. $name = is_array($item) ? ($item['name'] ?? '') : ($item->name ?? '');
  16. $kpCode = is_array($item) ? ($item['kp_code'] ?? '') : ($item->kp_code ?? '');
  17. if ($name !== '' && mb_strpos($questionText, $name) !== false) {
  18. $matched[] = [
  19. 'kp_code' => $kpCode,
  20. 'weight' => 1,
  21. ];
  22. }
  23. }
  24. return $matched;
  25. }
  26. public function matchKnowledgePointsByAi(string $questionText, array $candidates = [], ?string $context = null): array
  27. {
  28. if (empty($candidates)) {
  29. $candidates = $this->getCandidateKnowledgePoints();
  30. }
  31. $prompt = app(QuestionPromptService::class)->buildKnowledgeMatchPrompt($questionText, $candidates, $context);
  32. try {
  33. $result = app(AiClientService::class)->callJson($prompt);
  34. } catch (\Throwable $e) {
  35. return [];
  36. }
  37. $items = $result['knowledge_points'] ?? [];
  38. $matches = [];
  39. foreach ($items as $item) {
  40. $kpCode = $item['kp_code'] ?? null;
  41. if (!$kpCode) {
  42. continue;
  43. }
  44. $matches[] = [
  45. 'kp_code' => $kpCode,
  46. 'weight' => $item['weight'] ?? 1,
  47. ];
  48. }
  49. return $matches;
  50. }
  51. public function isValidKnowledgePoint(?string $kpCode): bool
  52. {
  53. if (!$kpCode) {
  54. return false;
  55. }
  56. $cacheKey = "kp-valid-{$kpCode}";
  57. return Cache::remember($cacheKey, now()->addMinutes(30), function () use ($kpCode) {
  58. return KnowledgePoint::query()->where('kp_code', $kpCode)->exists();
  59. });
  60. }
  61. public function getCandidateKnowledgePoints(int $limit = 300): array
  62. {
  63. return KnowledgePoint::query()
  64. ->select(['kp_code', 'name'])
  65. ->orderBy('kp_code')
  66. ->limit($limit)
  67. ->get()
  68. ->toArray();
  69. }
  70. public function inferKnowledgeWeights(array $questionStruct): array
  71. {
  72. $kps = $questionStruct['knowledge_points'] ?? [];
  73. return array_map(function ($kp) {
  74. return [
  75. 'kp_code' => $kp,
  76. 'weight' => 1,
  77. ];
  78. }, $kps);
  79. }
  80. }