knowledgeBases->pluck('id')->toArray(); if (empty($knowledgeBaseIds)) { return [ 'context' => '', 'sources' => [], ]; } try { // 使用 Scout/Meilisearch 原生过滤(与 DocumentSearchService 一致) $documents = Document::search($query) ->whereIn('knowledge_base_id', $knowledgeBaseIds) ->take(self::TOP_K) ->get(); } catch (\Exception $e) { Log::warning('Knowledge search failed', [ 'query' => $query, 'error' => $e->getMessage(), ]); return [ 'context' => '', 'sources' => [], ]; } if ($documents->isEmpty()) { return [ 'context' => '', 'sources' => [], ]; } $context = ''; $sources = []; foreach ($documents as $document) { $snippet = $this->extractSnippet($document); if (mb_strlen($context) + mb_strlen($snippet) > self::MAX_CONTEXT_LENGTH) { break; } $context .= $snippet . "\n\n"; $sources[] = [ 'id' => $document->id, 'title' => $document->title, 'knowledge_base' => $document->knowledgeBase?->name, ]; } return [ 'context' => trim($context), 'sources' => $sources, ]; } /** * 从文档中提取摘要片段 */ private function extractSnippet($document): string { $content = $document->markdown_preview ?? $document->description ?? ''; if (mb_strlen($content) <= 500) { return "【{$document->title}】\n{$content}"; } return "【{$document->title}】\n" . mb_substr($content, 0, 500) . '...'; } }