Fix: filters now ALWAYS work — auto-switches to hybrid when set
The bug: selecting a state filter in AI Search mode did nothing because HNSW vector search has no concept of SQL WHERE clauses. Results came back from any state. The fix: when ANY filter is set (state, role, or reliability > 0.5), the search automatically switches to hybrid mode which runs the SQL filter first, then AI-ranks within the filtered set. Users don't need to know about modes — filters just work. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
6a2cc0fb8f
commit
f9e2a0bbbe
@ -134,15 +134,20 @@ async function doSearch() {
|
|||||||
const btn = document.getElementById('search-btn');
|
const btn = document.getElementById('search-btn');
|
||||||
btn.disabled = true;
|
btn.disabled = true;
|
||||||
btn.textContent = 'Searching...';
|
btn.textContent = 'Searching...';
|
||||||
document.getElementById('results').innerHTML = '<div class="loading">Searching ' + (mode === 'crm' ? 'by keyword' : 'with AI') + '...</div>';
|
const searchLabel = effectiveMode === 'crm' ? 'by keyword' : effectiveMode === 'hybrid' ? 'with AI + filters' : 'with AI';
|
||||||
|
document.getElementById('results').innerHTML = '<div class="loading">Searching ' + searchLabel + '...</div>';
|
||||||
|
|
||||||
const t0 = Date.now();
|
const t0 = Date.now();
|
||||||
|
|
||||||
|
// If ANY filter is set, always use hybrid — filters only work through SQL
|
||||||
|
const hasFilters = state || role || rel > 0.5;
|
||||||
|
const effectiveMode = (mode === 'crm') ? 'crm' : (hasFilters ? 'hybrid' : mode);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let data;
|
let data;
|
||||||
|
|
||||||
if (mode === 'crm') {
|
if (effectiveMode === 'crm') {
|
||||||
// CRM keyword search — LIKE match
|
// CRM keyword search — exact LIKE match
|
||||||
let where = "resume_text LIKE '%" + query.replace(/'/g, "''") + "%'";
|
let where = "resume_text LIKE '%" + query.replace(/'/g, "''") + "%'";
|
||||||
if (state) where += " AND state = '" + state + "'";
|
if (state) where += " AND state = '" + state + "'";
|
||||||
if (role) where += " AND role = '" + role + "'";
|
if (role) where += " AND role = '" + role + "'";
|
||||||
@ -154,8 +159,8 @@ async function doSearch() {
|
|||||||
data = await r.json();
|
data = await r.json();
|
||||||
renderCRMResults(data, query, Date.now() - t0);
|
renderCRMResults(data, query, Date.now() - t0);
|
||||||
|
|
||||||
} else if (mode === 'ai') {
|
} else if (effectiveMode === 'ai') {
|
||||||
// Pure AI vector search
|
// Pure AI vector search — no filters, just meaning
|
||||||
const r = await fetch(GW + '/api/vectors/hnsw/search', {
|
const r = await fetch(GW + '/api/vectors/hnsw/search', {
|
||||||
method: 'POST', headers: {'Content-Type': 'application/json'},
|
method: 'POST', headers: {'Content-Type': 'application/json'},
|
||||||
body: JSON.stringify({index_name: 'workers_500k_v1', query: query, top_k: 10})
|
body: JSON.stringify({index_name: 'workers_500k_v1', query: query, top_k: 10})
|
||||||
@ -164,7 +169,7 @@ async function doSearch() {
|
|||||||
renderAIResults(data, query, Date.now() - t0);
|
renderAIResults(data, query, Date.now() - t0);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Hybrid — SQL filter + AI ranking
|
// Hybrid — SQL filters enforce structure, AI ranks by relevance
|
||||||
let filter = "CAST(reliability AS DOUBLE) >= " + rel;
|
let filter = "CAST(reliability AS DOUBLE) >= " + rel;
|
||||||
if (state) filter += " AND state = '" + state + "'";
|
if (state) filter += " AND state = '" + state + "'";
|
||||||
if (role) filter += " AND role = '" + role + "'";
|
if (role) filter += " AND role = '" + role + "'";
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user