2727
2828from src .langchain .retriever_factory import make_retriever
2929from src .langchain .trace import configure_emitter
30+ _FAISS_DIR_PATTERN = re .compile (r"^faiss_(?P<key>.+?)__(?P<embed>.+)$" )
31+
32+
3033def _fs_safe (value : str ) -> str :
3134 """Return a filesystem-safe slug for embedding model names."""
3235
3336 return re .sub (r"[^a-zA-Z0-9._-]+" , "-" , value )
3437
3538
39+ def _infer_key_from_faiss_dir (path : Path ) -> str | None :
40+ """Attempt to infer the sanitized key from a FAISS directory name."""
41+
42+ name = path .name
43+ if name .endswith ("_repacked" ):
44+ name = name [: - len ("_repacked" )]
45+ match = _FAISS_DIR_PATTERN .match (name )
46+ if match :
47+ return match .group ("key" )
48+ return None
49+
50+
3651ROOT = project_root
3752
3853MODES_REQUIRING_CHUNKS = {"bm25" , "hybrid" , "parent" , "hybrid+compression" }
@@ -239,6 +254,7 @@ def main():
239254 key_group .add_argument (
240255 "--index" ,
241256 dest = "index_path" ,
257+
242258 help = "Path to FAISS index directory (faiss_<key>__<embed_model>)" ,
243259 )
244260 parser .add_argument ("--embed-model" , default = "BAAI/bge-small-en-v1.5" )
@@ -314,8 +330,10 @@ def main():
314330 index_dir = Path (args .index_dir ).expanduser ()
315331
316332 docs : list [Document ] | None = None
333+
334+ key_safe : str | None = _fs_safe (args .key ) if args .key else None
335+
317336 key_arg = args .key
318- key_safe = _fs_safe (key_arg ) if key_arg else None
319337 expected_chunks , base_dir , repacked_dir , key_safe = _prepare_index_locations (
320338 key_safe = key_safe ,
321339 index_path = args .index_path ,
@@ -325,27 +343,56 @@ def main():
325343 )
326344
327345 # Prefer a repacked/merged index if available
346+
328347 faiss_dir : Path | None = None
329- for cand in (repacked_dir , base_dir ):
330- if (cand / "index.faiss" ).exists ():
331- faiss_dir = cand
332- break
348+ expected_chunks : Path | None = None
333349
334- if faiss_dir is None :
335- if base_dir .exists ():
336- shards = [p for p in base_dir .iterdir () if p .is_dir ()]
337- if shards :
338- raise SystemExit (
339- f"[lc_ask] FAISS shards found but no merged index: { base_dir } \n "
340- " • Merge shards before querying (merge step not completed)"
341- )
342- raise SystemExit (
343- "[lc_ask] FAISS dir not found: "
344- f"{ base_dir } (or repacked: { repacked_dir } ).\n "
345- f" • If you upgraded LangChain, try: make repack-faiss KEY={ args .key } EMBED_MODEL={ args .embed_model } \n "
346- f" • Or rebuild the index: python src/langchain/lc_build_index.py { args .key } "
350+ if args .index_path :
351+ faiss_dir = Path (args .index_path ).expanduser ()
352+ if not faiss_dir .exists ():
353+ raise SystemExit (f"[lc_ask] FAISS dir not found: { faiss_dir } " )
354+ if not (faiss_dir / "index.faiss" ).exists ():
355+ raise SystemExit (
356+ f"[lc_ask] index.faiss not found in { faiss_dir } . Provide a merged FAISS directory"
357+ )
358+ inferred_key = _infer_key_from_faiss_dir (faiss_dir )
359+ if inferred_key :
360+ key_safe = inferred_key
361+ if key_safe :
362+ expected_chunks = chunks_dir / f"lc_chunks_{ key_safe } .jsonl"
363+ else :
364+ key_safe = _fs_safe (args .key )
365+ expected_chunks , base_dir , repacked_dir = _resolve_paths (
366+ key = key_safe ,
367+ embed_model = args .embed_model ,
368+ chunks_dir = chunks_dir ,
369+ index_dir = index_dir ,
347370 )
348371
372+ # Prefer a repacked/merged index if available
373+ for cand in (repacked_dir , base_dir ):
374+ if (cand / "index.faiss" ).exists ():
375+ faiss_dir = cand
376+ break
377+
378+ if faiss_dir is None :
379+ if base_dir .exists ():
380+ shards = [p for p in base_dir .iterdir () if p .is_dir ()]
381+ if shards :
382+ raise SystemExit (
383+ f"[lc_ask] FAISS shards found but no merged index: { base_dir } \n "
384+ " • Merge shards before querying (merge step not completed)"
385+ )
386+ raise SystemExit (
387+ "[lc_ask] FAISS dir not found: "
388+ f"{ base_dir } (or repacked: { repacked_dir } ).\n "
389+ f" • If you upgraded LangChain, try: make repack-faiss KEY={ args .key } EMBED_MODEL={ args .embed_model } \n "
390+ f" • Or rebuild the index: python src/langchain/lc_build_index.py { args .key } "
391+ )
392+
393+ if faiss_dir is None :
394+ raise SystemExit ("[lc_ask] Unable to resolve FAISS directory" )
395+
349396 chunks_path = _locate_chunks_file (
350397 explicit_path = args .chunks_file ,
351398 chunks_dir = chunks_dir ,
@@ -360,10 +407,16 @@ def main():
360407 f"[lc_ask] chunks not found: { expected_chunks } – run lc_build_index for KEY={ args .key } "
361408 )
362409 else :
410+ if expected_chunks is None :
411+ raise SystemExit (
412+ f"[lc_ask] chunks not found for index at { faiss_dir } . Provide --chunks-file"
413+ )
363414 key_hint = key_arg or (key_safe if key_safe is not None else str (faiss_dir ))
415+ display_key = args .key if args .key else key_safe
364416 raise SystemExit (
365417 "[lc_ask] chunks not found: "
366418 f"{ expected_chunks } – run lc_build_index for { key_hint } "
419+
367420 )
368421
369422
0 commit comments