Spaces:
Runtime error
Runtime error
File size: 8,456 Bytes
7ab7df1 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 | """Integration tests for the RAG application."""
from unittest.mock import MagicMock, Mock, patch
import pytest
from models import create_embeddings, create_llm
from qa_chain import create_qa_chain
from utils import format_chat_history, format_context_with_highlight, messages_to_tuples
from vectorstore import load_or_create_vectorstore
@patch("vectorstore.Chroma")
@patch("models.HuggingFaceEmbeddings")
def test_integration_rag_flow(mock_embeddings_class, mock_chroma_class):
"""Test full RAG flow from embeddings to QA chain."""
# Setup mocks
mock_embeddings = MagicMock()
mock_embeddings_class.return_value = mock_embeddings
mock_vectorstore = MagicMock()
mock_vectorstore.get.return_value = {
"documents": ["Test document content"],
"metadatas": [{"source": "pdf/test.pdf", "page": 1}],
}
mock_vectorstore.as_retriever.return_value = MagicMock()
mock_chroma_class.return_value = mock_vectorstore
# Test full flow
embeddings = create_embeddings()
vectorstore = load_or_create_vectorstore(embeddings)
qa_chain = create_qa_chain(vectorstore)
assert embeddings is not None
assert vectorstore is not None
assert qa_chain is not None
@patch("models.ChatOpenAI")
def test_integration_llm_creation(mock_chat_openai):
"""Test LLM creation integration."""
mock_llm = MagicMock()
mock_chat_openai.return_value = mock_llm
llm = create_llm(streaming=True)
assert llm is not None
mock_chat_openai.assert_called_once()
def test_integration_chat_history_conversion():
"""Test integration of chat history conversion and formatting."""
messages = [
{"role": "user", "content": "Question 1"},
{"role": "assistant", "content": "Answer 1"},
{"role": "user", "content": "Question 2"},
]
# Convert to tuples
tuples = messages_to_tuples(messages)
assert len(tuples) == 1
assert tuples[0][0] == "Question 1"
# Format history
formatted = format_chat_history(tuples)
assert "Question 1" in formatted
assert "Answer 1" in formatted
def test_integration_context_formatting():
"""Test integration of context formatting with all features."""
from langchain_core.documents import Document
docs = [
Document(
page_content="This is test content about machine learning.",
metadata={"source": "pdf/test1.pdf", "page": 1},
),
Document(
page_content="Another document about neural networks.",
metadata={"source": "pdf/test2.pdf", "page": 2},
),
]
docs_with_scores = [(docs[0], 0.9), (docs[1], 0.8)]
hybrid_scores = [
(docs[0], 0.9, 0.85, 0.95),
(docs[1], 0.8, 0.75, 0.85),
]
result = format_context_with_highlight(
docs,
docs_with_scores=docs_with_scores,
rewritten_query="machine learning neural networks",
hybrid_scores=hybrid_scores,
)
assert "Sources:" in result
assert "test1.pdf" in result
assert "test2.pdf" in result
assert "π Rewritten:" in result
assert "machine learning neural networks" in result
assert "β" in result # Top chunk highlighted
assert "f:" in result # Fused score
assert "s:" in result # Semantic score
assert "k:" in result # Keyword score
@patch("qa_chain.create_llm")
@patch("qa_chain.format_chat_history")
def test_integration_qa_chain_streaming(mock_format_history, mock_create_llm, mock_vectorstore):
"""Test integration of QA chain streaming."""
from qa_chain import create_qa_chain
mock_format_history.return_value = "Previous: Test"
# Create proper mock chunks with content as property
from unittest.mock import PropertyMock
mock_chunk1 = MagicMock()
mock_chunk1.content = "This is "
mock_chunk2 = MagicMock()
mock_chunk2.content = "a test "
mock_chunk3 = MagicMock()
mock_chunk3.content = "response."
mock_llm = MagicMock()
mock_llm.stream.return_value = [mock_chunk1, mock_chunk2, mock_chunk3]
mock_create_llm.return_value = mock_llm
mock_retriever = MagicMock()
mock_doc = Mock(page_content="Retrieved context", metadata={"source": "test.pdf", "page": 1})
mock_retriever.invoke.return_value = [mock_doc]
mock_vectorstore.as_retriever.return_value = mock_retriever
qa_chain = create_qa_chain(mock_vectorstore)
# Mock the chain operator - this is what gets called in stream()
mock_chain = MagicMock()
mock_chain.stream.return_value = [mock_chunk1, mock_chunk2, mock_chunk3]
qa_chain._prompt.__or__ = MagicMock(return_value=mock_chain)
inputs = {
"question": "What is this?",
"chat_history": [("Previous question", "Previous answer")],
}
results = list(qa_chain.stream(inputs))
assert len(results) > 0
assert all("chunk" in r for r in results)
# Check that chunks are accumulated - they should be strings
final_chunk = results[-1]["chunk"]
# The chunks get accumulated, so we should see all three
assert isinstance(final_chunk, str) or hasattr(final_chunk, '__str__')
chunk_str = str(final_chunk) if not isinstance(final_chunk, str) else final_chunk
assert len(chunk_str) > 0
assert len(results[-1]["source_documents"]) > 0
@patch("retrievers.BM25Okapi")
def test_integration_hybrid_retrieval(mock_bm25, mock_vectorstore):
"""Test integration of hybrid retrieval."""
from retrievers import HybridRetriever
from langchain_core.documents import Document
mock_vectorstore.get.return_value = {
"documents": ["Document about AI", "Document about ML"],
"metadatas": [
{"source": "pdf/ai.pdf", "page": 1},
{"source": "pdf/ml.pdf", "page": 2},
],
}
doc1 = Document(
page_content="Document about AI",
metadata={"source": "pdf/ai.pdf", "page": 1},
)
doc2 = Document(
page_content="Document about ML",
metadata={"source": "pdf/ml.pdf", "page": 2},
)
mock_vectorstore.similarity_search_with_score.return_value = [
(doc1, 0.1),
(doc2, 0.2),
]
mock_bm25_instance = MagicMock()
mock_bm25_instance.get_scores.return_value = [0.8, 0.6]
mock_bm25.return_value = mock_bm25_instance
retriever = HybridRetriever(mock_vectorstore)
results = retriever.hybrid_search("AI machine learning", k=2, alpha=0.7)
assert len(results) == 2
assert all("doc" in r for r in results)
assert all("fused_score" in r for r in results)
assert all("semantic_score" in r for r in results)
assert all("keyword_score" in r for r in results)
# Check that scores are fused correctly
for result in results:
assert 0 <= result["fused_score"] <= 1
assert 0 <= result["semantic_score"] <= 1
assert 0 <= result["keyword_score"] <= 1
def test_integration_end_to_end_rag_query():
"""Test end-to-end RAG query processing."""
from qa_chain import QAChainWrapper
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.documents import Document
# Setup mocks
mock_vectorstore = MagicMock()
mock_vectorstore.get.return_value = {
"documents": ["RAG is Retrieval-Augmented Generation"],
"metadatas": [{"source": "pdf/rag.pdf", "page": 1}],
}
mock_retriever = MagicMock()
mock_retriever.invoke.return_value = [
Document(
page_content="RAG is Retrieval-Augmented Generation",
metadata={"source": "pdf/rag.pdf", "page": 1},
)
]
mock_vectorstore.as_retriever.return_value = mock_retriever
prompt = ChatPromptTemplate.from_template("Answer: {context}")
with patch("qa_chain.create_llm") as mock_create_llm:
mock_llm = MagicMock()
mock_llm.stream.return_value = [
MagicMock(content="RAG stands for "),
MagicMock(content="Retrieval-Augmented Generation."),
]
mock_create_llm.return_value = mock_llm
qa_chain = QAChainWrapper(mock_vectorstore, prompt)
inputs = {
"question": "What is RAG?",
"chat_history": [],
}
results = list(qa_chain.stream(inputs))
assert len(results) > 0
final_result = results[-1]
assert "chunk" in final_result
assert "source_documents" in final_result
assert len(final_result["source_documents"]) > 0
|