search method

Future<KnowledgeSearchResponse> search(
  1. String query, {
  2. KnowledgeSearchPolicy? policy,
  3. int limit = 5,
  4. int? contextLimit,
})

Implementation

Future<KnowledgeSearchResponse> search(
  String query, {
  KnowledgeSearchPolicy? policy,
  int limit = 5,
  int? contextLimit,
}) async {
  final snapshot = _snapshot;
  if (snapshot == null || _synchronizing) {
    throw StateError('Synchronize the index before searching.');
  }
  final budget = contextLimit ?? limit;
  if (query.trim().isEmpty || limit <= 0 || budget <= 0) {
    return KnowledgeSearchResponse(matches: [], context: [], notices: []);
  }
  final effective = policy ?? KnowledgeSearchPolicy();
  final eligible = _eligibleChunks(snapshot, effective);
  _searches++;
  try {
    final dense = <SearchResult>[];
    if (eligible.isNotEmpty) {
      final stored = await store.getEmbeddingsForChunks(
        eligible.keys.toSet(),
        source: embedder.sourceName,
        modelName: embeddingModelName,
      );
      if (stored.length != eligible.length) {
        throw StateError(
          'Dense search requires compatible embeddings for every eligible '
          'passage. Synchronize the index again.',
        );
      }
      final key = query.trim();
      final vector =
          _queryCache.remove(key) ?? await embedder.generateQueryVector(key);
      _queryCache[key] = vector;
      if (_queryCache.length > 100) {
        _queryCache.remove(_queryCache.keys.first);
      }
      for (final embedding in stored) {
        dense.add(
          SearchResult(
            chunk: eligible[embedding.chunkId]!,
            embedding: embedding,
            similarity: cosineSimilarity(vector, embedding.vector),
          ),
        );
      }
      dense.sort((a, b) {
        final score = b.similarity.compareTo(a.similarity);
        if (score != 0) return score;
        final path = a.chunk.sourcePath.compareTo(b.chunk.sourcePath);
        return path == 0 ? a.chunk.id.compareTo(b.chunk.id) : path;
      });
    }
    return _contextForEligible(
      snapshot,
      eligible,
      dense,
      policy: effective,
      limit: limit,
      budget: budget,
    );
  } finally {
    _searches--;
  }
}