Spaces:
Running
Running
| """ | |
| Smoke test: verify embedding model singleton is resilient to module-reload scenarios. | |
| Simulates the exact failure mode reported in the evaluation: | |
| 1. First call to _get_embedding_model() succeeds (registers + instantiates) | |
| 2. Resetting the module-level global to None (simulating a module reload / failed-first-attempt) | |
| 3. Second call should NOT crash with "already registered" β the fix must handle | |
| fastembed's class-level registry being pre-populated. | |
| Usage: | |
| cd AI Chatbot | |
| python -m scripts.test_embedding_singleton | |
| """ | |
| import sys | |
| import time | |
| sys.stdout.reconfigure(encoding="utf-8") # Windows-safe emoji | |
| print("=" * 60) | |
| print("Smoke Test: Embedding Singleton Resilience") | |
| print("=" * 60) | |
| def step(label: str, ok: bool): | |
| status = "PASS" if ok else "FAIL" | |
| print(f" [{status}] {label}") | |
| # ---- Step 1: first-time load (should succeed) ---- | |
| print("\n[Step 1] First-time load...") | |
| start = time.perf_counter() | |
| from app.vector_store import _get_embedding_model, embed_text | |
| try: | |
| model = _get_embedding_model() | |
| step("_get_embedding_model() returned an instance", model is not None) | |
| except Exception as e: | |
| step(f"_get_embedding_model() raised: {e}", False) | |
| sys.exit(1) | |
| elapsed = time.perf_counter() - start | |
| print(f" (took {elapsed:.1f}s β includes model download if first run)\n") | |
| # ---- Step 2: second call with cached model (should return immediately) ---- | |
| print("[Step 2] Second call (cached)...") | |
| try: | |
| model2 = _get_embedding_model() | |
| step("_get_embedding_model() returned the same instance", model2 is model) | |
| except Exception as e: | |
| step(f"_get_embedding_model() raised: {e}", False) | |
| sys.exit(1) | |
| print() | |
| # ---- Step 3: embed a test query (should produce 1024-dim vector) ---- | |
| print("[Step 3] embed_text produces a valid 1024-dim vector...") | |
| try: | |
| vec = embed_text("berapa pH optimal untuk selada hidroponik?") | |
| is_1024 = len(vec) == 1024 | |
| has_values = any(abs(v) > 1e-8 for v in vec[:10]) | |
| step(f"embed_text returned {len(vec)} floats", is_1024) | |
| step("first 10 values are non-zero (valid embedding)", has_values) | |
| except Exception as e: | |
| step(f"embed_text raised: {e}", False) | |
| sys.exit(1) | |
| print() | |
| # ---- Step 4: simulate module reload (reset global, keep class registry) ---- | |
| print("[Step 4] Simulating module reload β reset _embedding_model to None...") | |
| import app.vector_store as vs | |
| try: | |
| old_model = vs._embedding_model | |
| vs._embedding_model = None | |
| step("_embedding_model reset to None", vs._embedding_model is None) | |
| except Exception as e: | |
| step(f"reset failed: {e}", False) | |
| sys.exit(1) | |
| print() | |
| # ---- Step 5: the critical test β _get_embedding_model() with registry populated ---- | |
| print("[Step 5] Calling _get_embedding_model() after 'module reload'...") | |
| print(" (fastembed class-level registry already has the model from Step 1)") | |
| try: | |
| model3 = _get_embedding_model() | |
| step("_get_embedding_model() did NOT crash with 'already registered'", model3 is not None) | |
| step("instance is valid", hasattr(model3, "query_embed")) | |
| except Exception as e: | |
| step(f"CRASHED: {e}", False) | |
| sys.exit(1) | |
| print() | |
| # ---- Step 6: verify embed still works after reload simulation ---- | |
| print("[Step 6] embed_text works after 'module reload'...") | |
| try: | |
| vec2 = embed_text("bagaimana cara mengatasi defisiensi kalium pada tanaman cabai?") | |
| is_1024 = len(vec2) == 1024 | |
| step(f"embed_text returned {len(vec2)} floats", is_1024) | |
| # Quick sanity: same query should produce similar embedding | |
| from app.vector_store import EMBEDDING_DIM | |
| step(f"matches EMBEDDING_DIM={EMBEDDING_DIM}", len(vec2) == EMBEDDING_DIM) | |
| except Exception as e: | |
| step(f"embed_text raised: {e}", False) | |
| sys.exit(1) | |
| print() | |
| # ---- Done ---- | |
| print("=" * 60) | |
| print("ALL STEPS PASSED β singleton fix is working correctly") | |
| print("=" * 60) | |