Carta Clara: carta QR, administración y lectura de fotos con Gemini
Una carta QR con panel por restaurante y lectura de fotos mediante Gemini. Código abierto, edición manual y revisión antes de incorporar platos.
Aprende a filtrar resultados de búsqueda por relevancia semántica: combina similitud vectorial (embeddings), overlap léxico y reglas de dominio con thresholds y scoring.

El filtrado por relevancia semántica mejora la calidad de resultados de búsqueda eliminando matches irrelevantes. En este tutorial aprenderás a implementar filtros inteligentes que combinan similitud vectorial con lógica de negocio.
public class SemanticRelevanceFilter
{
private const double MinVectorScore = 0.35;
private const double MinLexicalOverlap = 0.2;
public async Task<List<SearchResult>> FilterRelevantResultsAsync(
string query,
List<SearchResult> candidates,
SearchContext context)
{
var queryTokens = TokenizeQuery(query);
var filtered = new List<SearchResult>();
foreach (var candidate in candidates)
{
var relevanceScore = CalculateRelevance(
query,
queryTokens,
candidate,
context);
if (relevanceScore.IsRelevant)
{
candidate.RelevanceScore = relevanceScore.Score;
candidate.RelevanceReason = relevanceScore.Reason;
filtered.Add(candidate);
}
}
return filtered.OrderByDescending(r => r.RelevanceScore).ToList();
}
private RelevanceScore CalculateRelevance(
string query,
HashSet<string> queryTokens,
SearchResult candidate,
SearchContext context)
{
// 1. Vector score check
if (candidate.VectorScore < MinVectorScore)
{
return RelevanceScore.NotRelevant("Vector score too low");
}
// 2. Lexical overlap check
var candidateTokens = TokenizeText(candidate.Description);
var overlap = CalculateLexicalOverlap(queryTokens, candidateTokens);
if (overlap < MinLexicalOverlap)
{
return RelevanceScore.NotRelevant("Insufficient lexical overlap");
}
// 3. Domain match check
if (context.Domain != null)
{
if (!MatchesDomain(candidate, context.Domain))
{
return RelevanceScore.NotRelevant("Domain mismatch");
}
}
// Calculate final score
var finalScore = (candidate.VectorScore * 0.6) +
(overlap * 0.3) +
(DomainBonus(candidate, context) * 0.1);
return RelevanceScore.Relevant(finalScore, "Passed all checks");
}
}
Palabras clave: semantic relevance, filtering, search quality, vector similarity, lexical overlap