ketannnn commited on
Commit
7bd1c28
·
1 Parent(s): 20ae104

fix: use real candidate count, remove stage2 cap, add full error logging

Browse files
backend/src/matching/stage2.py CHANGED
@@ -1,6 +1,9 @@
 
1
  from typing import Any
2
  from ..ml.reranker import rerank
3
 
 
 
4
 
5
  def _compute_gaps(jd: dict, candidate: dict) -> list[dict]:
6
  gaps = []
@@ -102,7 +105,13 @@ async def stage2_rerank(jd: dict, shortlist: list[dict]) -> list[dict]:
102
 
103
  from fastapi.concurrency import run_in_threadpool
104
  from .reranker import rerank
105
- reranker_scores = await run_in_threadpool(rerank, jd_query, passages)
 
 
 
 
 
 
106
 
107
  weights = jd.get("custom_weights", {})
108
  results = _recompute_final_score(shortlist, reranker_scores, weights)
@@ -110,4 +119,5 @@ async def stage2_rerank(jd: dict, shortlist: list[dict]) -> list[dict]:
110
  for cand in results:
111
  cand["gaps"] = _compute_gaps(jd, cand)
112
 
113
- return results[:250]
 
 
1
+ import logging
2
  from typing import Any
3
  from ..ml.reranker import rerank
4
 
5
+ logger = logging.getLogger(__name__)
6
+
7
 
8
  def _compute_gaps(jd: dict, candidate: dict) -> list[dict]:
9
  gaps = []
 
105
 
106
  from fastapi.concurrency import run_in_threadpool
107
  from .reranker import rerank
108
+ try:
109
+ logger.info(f"[Stage 2] Starting neural reranking of {len(passages)} candidates...")
110
+ reranker_scores = await run_in_threadpool(rerank, jd_query, passages)
111
+ logger.info(f"[Stage 2] Reranking complete. Got {len(reranker_scores)} scores.")
112
+ except Exception as exc:
113
+ logger.exception(f"[Stage 2] FATAL: Neural reranker crashed — {exc}")
114
+ raise
115
 
116
  weights = jd.get("custom_weights", {})
117
  results = _recompute_final_score(shortlist, reranker_scores, weights)
 
119
  for cand in results:
120
  cand["gaps"] = _compute_gaps(jd, cand)
121
 
122
+ # Return ALL candidates — no arbitrary cap
123
+ return results
backend/src/routers/matching.py CHANGED
@@ -1,11 +1,14 @@
1
  import uuid
2
  import json
 
3
  import redis.asyncio as redis
4
  from datetime import datetime, timezone
5
  from fastapi import APIRouter, Depends, HTTPException, Request, Query
6
  from sqlalchemy.ext.asyncio import AsyncSession
7
  from sqlalchemy import select, delete
8
 
 
 
9
  from ..database import get_db
10
  from ..config import get_settings
11
  from ..models.jd import JobDescription
@@ -115,7 +118,8 @@ async def trigger_match(
115
  inserted_mrs.append(mr)
116
 
117
  await db.commit()
118
- except Exception:
 
119
  await db.rollback()
120
  raise
121
 
 
1
  import uuid
2
  import json
3
+ import logging
4
  import redis.asyncio as redis
5
  from datetime import datetime, timezone
6
  from fastapi import APIRouter, Depends, HTTPException, Request, Query
7
  from sqlalchemy.ext.asyncio import AsyncSession
8
  from sqlalchemy import select, delete
9
 
10
+ logger = logging.getLogger(__name__)
11
+
12
  from ..database import get_db
13
  from ..config import get_settings
14
  from ..models.jd import JobDescription
 
118
  inserted_mrs.append(mr)
119
 
120
  await db.commit()
121
+ except Exception as exc:
122
+ logger.exception(f"[trigger_match] FATAL ERROR for JD {jd_id}: {exc}")
123
  await db.rollback()
124
  raise
125
 
frontend/src/app/pipeline/page.tsx CHANGED
@@ -173,14 +173,24 @@ export default function PipelinePage() {
173
 
174
  const runMatches = async (jdIds: string[], sessionId: string, currentState: PipelineState) => {
175
  let pendingJds = [...jdIds];
176
-
 
 
 
 
 
 
 
 
 
177
  const pollMatches = async () => {
178
  try {
179
  const stillPending: string[] = [];
180
-
181
  for (const jdId of pendingJds) {
182
  try {
183
- await api.triggerMatch(jdId, sessionId, 500, 500); // Pass ALL candidates through both stages
 
184
  } catch (e: any) {
185
  if (e.message === "202_ACCEPTED") {
186
  stillPending.push(jdId);
 
173
 
174
  const runMatches = async (jdIds: string[], sessionId: string, currentState: PipelineState) => {
175
  let pendingJds = [...jdIds];
176
+
177
+ // Fetch the ACTUAL number of ingested candidates — never hardcode a cap
178
+ let candidateCount = 100; // safe fallback
179
+ try {
180
+ const countRes = await api.candidateCount(sessionId);
181
+ candidateCount = countRes.count;
182
+ } catch (_) {
183
+ // If count fetch fails, fall back to 100
184
+ }
185
+
186
  const pollMatches = async () => {
187
  try {
188
  const stillPending: string[] = [];
189
+
190
  for (const jdId of pendingJds) {
191
  try {
192
+ // Pass EXACT candidate count as both Stage 1 and Stage 2 top_k
193
+ await api.triggerMatch(jdId, sessionId, candidateCount, candidateCount);
194
  } catch (e: any) {
195
  if (e.message === "202_ACCEPTED") {
196
  stillPending.push(jdId);