* fix: auto-detect normalized embeddings and use cosine distance - Add automatic detection for normalized embedding models (OpenAI, Voyage AI, Cohere) - Automatically set distance_metric='cosine' for normalized embeddings - Add warnings when using non-optimal distance metrics - Implement manual L2 normalization in HNSW backend (custom Faiss build lacks normalize_L2) - Fix DiskANN zmq_port compatibility with lazy loading strategy - Add documentation for normalized embeddings feature This fixes the low accuracy issue when using OpenAI text-embedding-3-small model with default MIPS metric. * style: format * feat: add OpenAI embeddings support to google_history_reader_leann.py - Add --embedding-model and --embedding-mode arguments - Support automatic detection of normalized embeddings - Works correctly with cosine distance for OpenAI embeddings * feat: add --use-existing-index option to google_history_reader_leann.py - Allow using existing index without rebuilding - Useful for testing pre-built indices * fix: Improve OpenAI embeddings handling in HNSW backend * fix: improve macOS C++ compatibility and add CI tests * refactor: improve test structure and fix main_cli example - Move pytest configuration from pytest.ini to pyproject.toml - Remove unnecessary run_tests.py script (use test extras instead) - Fix main_cli_example.py to properly use command line arguments for LLM config - Add test_readme_examples.py to test code examples from README - Refactor tests to use pytest fixtures and parametrization - Update test documentation to reflect new structure - Set proper environment variables in CI for test execution * fix: add --distance-metric support to DiskANN embedding server and remove obsolete macOS ABI test markers - Add --distance-metric parameter to diskann_embedding_server.py for consistency with other backends - Remove pytest.skip and pytest.xfail markers for macOS C++ ABI issues as they have been fixed - Fix test assertions to handle SearchResult objects correctly - All tests now pass on macOS with the C++ ABI compatibility fixes * chore: update lock file with test dependencies * docs: remove obsolete C++ ABI compatibility warnings - Remove outdated macOS C++ compatibility warnings from README - Simplify CI workflow by removing macOS-specific failure handling - All tests now pass consistently on macOS after ABI fixes * fix: update macOS deployment target for DiskANN to 13.3 - DiskANN uses sgesdd_ LAPACK function which is only available on macOS 13.3+ - Update MACOSX_DEPLOYMENT_TARGET from 11.0 to 13.3 for DiskANN builds - This fixes the compilation error on GitHub Actions macOS runners * fix: align Python version requirements to 3.9 - Update root project to support Python 3.9, matching subpackages - Restore macOS Python 3.9 support in CI - This fixes the CI failure for Python 3.9 environments * fix: handle MPS memory issues in CI tests - Use smaller MiniLM-L6-v2 model (384 dimensions) for README tests in CI - Skip other memory-intensive tests in CI environment - Add minimal CI tests that don't require model loading - Set CI environment variable and disable MPS fallback - Ensure README examples always run correctly in CI * fix: remove Python 3.10+ dependencies for compatibility - Comment out llama-index-readers-docling and llama-index-node-parser-docling - These packages require Python >= 3.10 and were causing CI failures on Python 3.9 - Regenerate uv.lock file to resolve dependency conflicts * fix: use virtual environment in CI instead of system packages - uv-managed Python environments don't allow --system installs - Create and activate virtual environment before installing packages - Update all CI steps to use the virtual environment * add some env in ci * fix: use --find-links to install platform-specific wheels - Let uv automatically select the correct wheel for the current platform - Fixes error when trying to install macOS wheels on Linux - Simplifies the installation logic * fix: disable OpenMP parallelism in CI to avoid libomp crashes - Set OMP_NUM_THREADS=1 to avoid OpenMP thread synchronization issues - Set MKL_NUM_THREADS=1 for single-threaded MKL operations - This prevents segfaults in LayerNorm on macOS CI runners - Addresses the libomp compatibility issues with PyTorch on Apple Silicon * skip several macos test because strange issue on ci --------- Co-authored-by: yichuan520030910320 <yichuan_wang@berkeley.edu>
121 lines
3.7 KiB
Python
121 lines
3.7 KiB
Python
"""
|
|
Test main_cli_example functionality using pytest.
|
|
"""
|
|
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
|
|
@pytest.fixture
|
|
def test_data_dir():
|
|
"""Return the path to test data directory."""
|
|
return Path("examples/data")
|
|
|
|
|
|
@pytest.mark.skipif(
|
|
os.environ.get("CI") == "true", reason="Skip model tests in CI to avoid MPS memory issues"
|
|
)
|
|
def test_main_cli_simulated(test_data_dir):
|
|
"""Test main_cli with simulated LLM."""
|
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
# Use a subdirectory that doesn't exist yet to force index creation
|
|
index_dir = Path(temp_dir) / "test_index"
|
|
cmd = [
|
|
sys.executable,
|
|
"examples/main_cli_example.py",
|
|
"--llm",
|
|
"simulated",
|
|
"--embedding-model",
|
|
"facebook/contriever",
|
|
"--embedding-mode",
|
|
"sentence-transformers",
|
|
"--index-dir",
|
|
str(index_dir),
|
|
"--data-dir",
|
|
str(test_data_dir),
|
|
"--query",
|
|
"What is Pride and Prejudice about?",
|
|
]
|
|
|
|
env = os.environ.copy()
|
|
env["HF_HUB_DISABLE_SYMLINKS"] = "1"
|
|
env["TOKENIZERS_PARALLELISM"] = "false"
|
|
|
|
result = subprocess.run(cmd, capture_output=True, text=True, timeout=600, env=env)
|
|
|
|
# Check return code
|
|
assert result.returncode == 0, f"Command failed: {result.stderr}"
|
|
|
|
# Verify output
|
|
output = result.stdout + result.stderr
|
|
assert "Leann index built at" in output or "Using existing index" in output
|
|
assert "This is a simulated answer" in output
|
|
|
|
|
|
@pytest.mark.skipif(not os.environ.get("OPENAI_API_KEY"), reason="OpenAI API key not available")
|
|
def test_main_cli_openai(test_data_dir):
|
|
"""Test main_cli with OpenAI embeddings."""
|
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
# Use a subdirectory that doesn't exist yet to force index creation
|
|
index_dir = Path(temp_dir) / "test_index_openai"
|
|
cmd = [
|
|
sys.executable,
|
|
"examples/main_cli_example.py",
|
|
"--llm",
|
|
"simulated", # Use simulated LLM to avoid GPT-4 costs
|
|
"--embedding-model",
|
|
"text-embedding-3-small",
|
|
"--embedding-mode",
|
|
"openai",
|
|
"--index-dir",
|
|
str(index_dir),
|
|
"--data-dir",
|
|
str(test_data_dir),
|
|
"--query",
|
|
"What is Pride and Prejudice about?",
|
|
]
|
|
|
|
env = os.environ.copy()
|
|
env["TOKENIZERS_PARALLELISM"] = "false"
|
|
|
|
result = subprocess.run(cmd, capture_output=True, text=True, timeout=600, env=env)
|
|
|
|
assert result.returncode == 0, f"Command failed: {result.stderr}"
|
|
|
|
# Verify cosine distance was used
|
|
output = result.stdout + result.stderr
|
|
assert any(
|
|
msg in output
|
|
for msg in [
|
|
"distance_metric='cosine'",
|
|
"Automatically setting distance_metric='cosine'",
|
|
"Using cosine distance",
|
|
]
|
|
)
|
|
|
|
|
|
def test_main_cli_error_handling(test_data_dir):
|
|
"""Test main_cli with invalid parameters."""
|
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
cmd = [
|
|
sys.executable,
|
|
"examples/main_cli_example.py",
|
|
"--llm",
|
|
"invalid_llm_type",
|
|
"--index-dir",
|
|
temp_dir,
|
|
"--data-dir",
|
|
str(test_data_dir),
|
|
]
|
|
|
|
result = subprocess.run(cmd, capture_output=True, text=True, timeout=60)
|
|
|
|
# Should fail with invalid LLM type
|
|
assert result.returncode != 0
|
|
assert "Unknown LLM type" in result.stderr or "invalid_llm_type" in result.stderr
|