7a0da7932b
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
436 lines
15 KiB
Python
436 lines
15 KiB
Python
"""Test demonstrating programmatic access with Langchain Ollama LLM and in-memory vector retriever."""
|
|
|
|
import pytest
|
|
from unittest.mock import patch, MagicMock
|
|
import requests
|
|
from langchain_ollama import OllamaEmbeddings, OllamaLLM
|
|
from langchain_community.vectorstores import FAISS
|
|
from langchain_core.retrievers import Document
|
|
|
|
from local_deep_research.api import (
|
|
quick_summary,
|
|
detailed_research,
|
|
generate_report,
|
|
)
|
|
from local_deep_research.llm import clear_llm_registry
|
|
|
|
|
|
def _is_ollama_running():
|
|
"""Check if Ollama service is running."""
|
|
try:
|
|
response = requests.get("http://localhost:11434/api/tags", timeout=1)
|
|
return response.status_code == 200
|
|
except Exception:
|
|
return False
|
|
|
|
|
|
# Skip entire module if Ollama is not running to avoid fixture initialization hangs
|
|
pytestmark = pytest.mark.skipif(
|
|
not _is_ollama_running(),
|
|
reason="Ollama is not running - skipping all Ollama integration tests",
|
|
)
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def clear_registries():
|
|
"""Clear registries before and after each test."""
|
|
clear_llm_registry()
|
|
yield
|
|
clear_llm_registry()
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_documents():
|
|
"""Create sample documents for the vector store."""
|
|
docs = [
|
|
Document(
|
|
page_content="Machine learning is a subset of artificial intelligence that enables systems to learn from data.",
|
|
metadata={"source": "ml_basics.txt", "topic": "machine_learning"},
|
|
),
|
|
Document(
|
|
page_content="Deep learning uses neural networks with multiple layers to extract features from raw data.",
|
|
metadata={"source": "dl_intro.txt", "topic": "deep_learning"},
|
|
),
|
|
Document(
|
|
page_content="Natural language processing allows computers to understand and generate human language.",
|
|
metadata={"source": "nlp_guide.txt", "topic": "nlp"},
|
|
),
|
|
Document(
|
|
page_content="Computer vision enables machines to interpret and analyze visual information from images and videos.",
|
|
metadata={"source": "cv_overview.txt", "topic": "computer_vision"},
|
|
),
|
|
Document(
|
|
page_content="Reinforcement learning trains agents to make decisions by rewarding desired behaviors.",
|
|
metadata={
|
|
"source": "rl_basics.txt",
|
|
"topic": "reinforcement_learning",
|
|
},
|
|
),
|
|
]
|
|
return docs
|
|
|
|
|
|
@pytest.fixture
|
|
def ollama_llm():
|
|
"""Create an Ollama LLM instance."""
|
|
# Using gemma3n:e4b as requested
|
|
return OllamaLLM(
|
|
model="gemma3n:e4b",
|
|
temperature=0.7,
|
|
)
|
|
|
|
|
|
@pytest.fixture
|
|
def memory_retriever(sample_documents):
|
|
"""Create an in-memory vector store retriever."""
|
|
# Create embeddings using the specified multilingual model
|
|
embeddings = OllamaEmbeddings(
|
|
model="jeffh/intfloat-multilingual-e5-large-instruct:f16"
|
|
)
|
|
|
|
# Create FAISS vector store from documents
|
|
vectorstore = FAISS.from_documents(
|
|
documents=sample_documents, embedding=embeddings
|
|
)
|
|
|
|
# Create retriever from vector store
|
|
retriever = vectorstore.as_retriever(
|
|
search_kwargs={"k": 3} # Return top 3 most relevant documents
|
|
)
|
|
|
|
return retriever
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_search_system():
|
|
"""Create a mock search system for testing."""
|
|
system = MagicMock()
|
|
system.analyze_topic.return_value = {
|
|
"current_knowledge": "Analysis using Ollama LLM and in-memory retriever",
|
|
"findings": [
|
|
"Successfully retrieved relevant documents from vector store",
|
|
"Ollama LLM provided coherent responses",
|
|
],
|
|
"iterations": 2,
|
|
"questions": {
|
|
"iteration_1": ["What is the main concept?"],
|
|
"iteration_2": ["How is it applied in practice?"],
|
|
},
|
|
"formatted_findings": "## Research Summary\n- Vector retrieval worked effectively",
|
|
"all_links_of_system": [],
|
|
}
|
|
system.model = MagicMock()
|
|
return system
|
|
|
|
|
|
@pytest.mark.skipif(
|
|
not _is_ollama_running(),
|
|
reason="Ollama is not running - skipping integration test",
|
|
)
|
|
def test_quick_summary_with_ollama_and_memory_retriever(
|
|
ollama_llm, memory_retriever, mock_search_system
|
|
):
|
|
"""Test quick_summary using Ollama LLM and in-memory vector retriever."""
|
|
|
|
with patch(
|
|
"local_deep_research.api.research_functions._init_search_system"
|
|
) as mock_init:
|
|
mock_init.return_value = mock_search_system
|
|
|
|
# Use programmatic API with Ollama and memory retriever
|
|
result = quick_summary(
|
|
query="What is deep learning and how does it relate to machine learning?",
|
|
llms={"ollama_llm": ollama_llm},
|
|
retrievers={"memory_docs": memory_retriever},
|
|
provider="ollama_llm",
|
|
search_tool="memory_docs",
|
|
temperature=0.5,
|
|
)
|
|
|
|
# Verify result structure
|
|
assert "summary" in result
|
|
assert (
|
|
result["summary"]
|
|
== "Analysis using Ollama LLM and in-memory retriever"
|
|
)
|
|
assert len(result["findings"]) == 2
|
|
assert "vector store" in result["findings"][0].lower()
|
|
|
|
# Verify components were configured correctly
|
|
init_kwargs = mock_init.call_args[1]
|
|
assert init_kwargs["provider"] == "ollama_llm"
|
|
assert init_kwargs["search_tool"] == "memory_docs"
|
|
assert init_kwargs["temperature"] == 0.5
|
|
|
|
|
|
@pytest.mark.skipif(
|
|
not _is_ollama_running(),
|
|
reason="Ollama is not running - skipping integration test",
|
|
)
|
|
def test_detailed_research_with_ollama_and_memory_retriever(
|
|
ollama_llm, memory_retriever, mock_search_system
|
|
):
|
|
"""Test detailed_research with Ollama and memory retriever."""
|
|
|
|
with patch(
|
|
"local_deep_research.api.research_functions._init_search_system"
|
|
) as mock_init:
|
|
mock_init.return_value = mock_search_system
|
|
|
|
result = detailed_research(
|
|
query="Explain the differences between various machine learning approaches",
|
|
llms={"ollama": ollama_llm},
|
|
retrievers={"local_docs": memory_retriever},
|
|
provider="ollama",
|
|
search_tool="local_docs",
|
|
iterations=3,
|
|
questions_per_iteration=2,
|
|
)
|
|
|
|
# Verify detailed research results
|
|
assert (
|
|
result["query"]
|
|
== "Explain the differences between various machine learning approaches"
|
|
)
|
|
assert (
|
|
result["summary"]
|
|
== "Analysis using Ollama LLM and in-memory retriever"
|
|
)
|
|
assert result["metadata"]["iterations_requested"] == 3
|
|
assert result["metadata"]["search_tool"] == "local_docs"
|
|
|
|
|
|
@pytest.mark.skipif(
|
|
not _is_ollama_running(),
|
|
reason="Ollama is not running - skipping integration test",
|
|
)
|
|
def test_generate_report_with_ollama_and_memory_retriever(
|
|
ollama_llm, memory_retriever
|
|
):
|
|
"""Test report generation using Ollama and memory retriever."""
|
|
|
|
with patch(
|
|
"local_deep_research.api.research_functions._init_search_system"
|
|
) as mock_init:
|
|
with patch(
|
|
"local_deep_research.api.research_functions.IntegratedReportGenerator"
|
|
) as mock_report_gen:
|
|
# Setup mocks
|
|
mock_system = MagicMock()
|
|
mock_system.analyze_topic.return_value = {
|
|
"findings": "Initial ML findings"
|
|
}
|
|
mock_init.return_value = mock_system
|
|
|
|
mock_generator = MagicMock()
|
|
mock_generator.generate_report.return_value = {
|
|
"content": "# Machine Learning Overview\n\n## Introduction\nThis report covers key ML concepts from local documents.",
|
|
"metadata": {
|
|
"query": "machine learning overview",
|
|
"sources_used": 5,
|
|
},
|
|
}
|
|
mock_report_gen.return_value = mock_generator
|
|
|
|
# Generate report
|
|
result = generate_report(
|
|
query="Create a comprehensive overview of machine learning concepts",
|
|
llms={"ollama": ollama_llm},
|
|
retrievers={"vector_store": memory_retriever},
|
|
provider="ollama",
|
|
search_tool="vector_store",
|
|
searches_per_section=2,
|
|
)
|
|
|
|
# Verify report generation
|
|
assert "content" in result
|
|
assert "# Machine Learning Overview" in result["content"]
|
|
assert "local documents" in result["content"]
|
|
|
|
# Verify configuration
|
|
init_kwargs = mock_init.call_args[1]
|
|
assert init_kwargs["provider"] == "ollama"
|
|
assert init_kwargs["search_tool"] == "vector_store"
|
|
|
|
|
|
@pytest.mark.skipif(
|
|
not _is_ollama_running(),
|
|
reason="Ollama is not running - skipping integration test",
|
|
)
|
|
def test_custom_vector_store_with_more_documents():
|
|
"""Test creating a larger in-memory vector store."""
|
|
|
|
# Create more documents
|
|
extended_docs = [
|
|
Document(
|
|
page_content="Transfer learning allows models trained on one task to be adapted for related tasks.",
|
|
metadata={"source": "transfer_learning.txt"},
|
|
),
|
|
Document(
|
|
page_content="Attention mechanisms help models focus on relevant parts of the input data.",
|
|
metadata={"source": "attention.txt"},
|
|
),
|
|
Document(
|
|
page_content="Gradient descent is an optimization algorithm used to train neural networks.",
|
|
metadata={"source": "optimization.txt"},
|
|
),
|
|
Document(
|
|
page_content="Convolutional neural networks are particularly effective for image processing tasks.",
|
|
metadata={"source": "cnn.txt"},
|
|
),
|
|
Document(
|
|
page_content="Recurrent neural networks can process sequential data like text or time series.",
|
|
metadata={"source": "rnn.txt"},
|
|
),
|
|
]
|
|
|
|
# Create vector store with extended documents
|
|
embeddings = OllamaEmbeddings(
|
|
model="jeffh/intfloat-multilingual-e5-large-instruct:f16"
|
|
)
|
|
vectorstore = FAISS.from_documents(
|
|
documents=extended_docs, embedding=embeddings
|
|
)
|
|
|
|
# Create retriever with different search parameters
|
|
retriever = vectorstore.as_retriever(
|
|
search_type="similarity",
|
|
search_kwargs={"k": 5}, # Return top 5 documents
|
|
)
|
|
|
|
# Create Ollama LLM
|
|
llm = OllamaLLM(model="gemma3n:e4b", temperature=0.3)
|
|
|
|
with patch(
|
|
"local_deep_research.api.research_functions._init_search_system"
|
|
) as mock_init:
|
|
mock_system = MagicMock()
|
|
mock_system.analyze_topic.return_value = {
|
|
"current_knowledge": "Extended document analysis complete",
|
|
"findings": ["Found relevant information about neural networks"],
|
|
}
|
|
mock_init.return_value = mock_system
|
|
|
|
result = quick_summary(
|
|
query="How do different types of neural networks work?",
|
|
llms={"ollama": llm},
|
|
retrievers={"extended_docs": retriever},
|
|
provider="ollama",
|
|
search_tool="extended_docs",
|
|
)
|
|
|
|
assert "summary" in result
|
|
assert result["summary"] == "Extended document analysis complete"
|
|
|
|
|
|
@pytest.mark.skipif(
|
|
not _is_ollama_running(),
|
|
reason="Ollama is not running - skipping integration test",
|
|
)
|
|
def test_multiple_retrievers_with_ollama():
|
|
"""Test using multiple in-memory retrievers with Ollama."""
|
|
|
|
# Create first retriever for ML topics
|
|
ml_docs = [
|
|
Document(
|
|
page_content="Supervised learning uses labeled data for training."
|
|
),
|
|
Document(
|
|
page_content="Unsupervised learning finds patterns in unlabeled data."
|
|
),
|
|
]
|
|
|
|
# Create second retriever for application topics
|
|
app_docs = [
|
|
Document(
|
|
page_content="ML is used in recommendation systems for personalized content."
|
|
),
|
|
Document(
|
|
page_content="ML powers autonomous vehicles through computer vision and sensor fusion."
|
|
),
|
|
]
|
|
|
|
embeddings = OllamaEmbeddings(
|
|
model="jeffh/intfloat-multilingual-e5-large-instruct:f16"
|
|
)
|
|
|
|
ml_vectorstore = FAISS.from_documents(ml_docs, embeddings)
|
|
app_vectorstore = FAISS.from_documents(app_docs, embeddings)
|
|
|
|
ml_retriever = ml_vectorstore.as_retriever()
|
|
app_retriever = app_vectorstore.as_retriever()
|
|
|
|
ollama_llm = OllamaLLM(model="gemma3n:e4b")
|
|
|
|
with patch(
|
|
"local_deep_research.api.research_functions._init_search_system"
|
|
) as mock_init:
|
|
mock_system = MagicMock()
|
|
mock_system.analyze_topic.return_value = {
|
|
"current_knowledge": "Analysis from multiple vector stores",
|
|
"findings": ["ML concepts retrieved", "Applications identified"],
|
|
}
|
|
mock_init.return_value = mock_system
|
|
|
|
result = quick_summary(
|
|
query="What are ML techniques and their applications?",
|
|
llms={"ollama": ollama_llm},
|
|
retrievers={
|
|
"ml_concepts": ml_retriever,
|
|
"ml_applications": app_retriever,
|
|
},
|
|
provider="ollama",
|
|
search_tool="ml_concepts", # Use a registered retriever
|
|
)
|
|
|
|
assert "summary" in result
|
|
assert "multiple vector stores" in result["summary"]
|
|
|
|
|
|
@pytest.mark.skipif(
|
|
not _is_ollama_running(),
|
|
reason="Ollama is not running - skipping integration test",
|
|
)
|
|
def test_simple_ollama_factory_pattern():
|
|
"""Test using a factory function to create Ollama instances."""
|
|
|
|
def create_ollama_llm(model_name="gemma3n:e4b", temperature=0.7, **kwargs):
|
|
"""Factory function for creating configured Ollama instances."""
|
|
return OllamaLLM(
|
|
model=model_name,
|
|
temperature=temperature,
|
|
num_predict=kwargs.get("max_tokens", 256),
|
|
)
|
|
|
|
# Create simple in-memory retriever
|
|
docs = [Document(page_content="Test content for factory pattern demo.")]
|
|
embeddings = OllamaEmbeddings(
|
|
model="jeffh/intfloat-multilingual-e5-large-instruct:f16"
|
|
)
|
|
vectorstore = FAISS.from_documents(docs, embeddings)
|
|
retriever = vectorstore.as_retriever()
|
|
|
|
with patch(
|
|
"local_deep_research.api.research_functions._init_search_system"
|
|
) as mock_init:
|
|
mock_system = MagicMock()
|
|
mock_system.analyze_topic.return_value = {
|
|
"current_knowledge": "Factory pattern test successful",
|
|
"findings": [],
|
|
}
|
|
mock_init.return_value = mock_system
|
|
|
|
result = quick_summary(
|
|
query="Test factory pattern",
|
|
llms={"ollama_factory": create_ollama_llm},
|
|
retrievers={"test_docs": retriever},
|
|
provider="ollama_factory",
|
|
search_tool="test_docs",
|
|
model_name="gemma3n:e4b",
|
|
temperature=0.2,
|
|
max_tokens=512,
|
|
)
|
|
|
|
assert "summary" in result
|
|
assert "Factory pattern test successful" in result["summary"]
|