feat: solution for '8. Самописный поисковый агент на основе deep agents from scratch'
This commit is contained in:
+10
-61
@@ -1,68 +1,17 @@
|
||||
"""
|
||||
Unit tests for the SearchAgent implementation.
|
||||
Unit tests for the base Agent class.
|
||||
"""
|
||||
|
||||
import unittest
|
||||
|
||||
from src.agent import SearchAgent, Result
|
||||
import pytest
|
||||
from src.agent import Agent
|
||||
|
||||
|
||||
class TestSearchAgent(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.corpus = [
|
||||
"The quick brown fox jumps over the lazy dog.",
|
||||
"Deep learning models can capture complex patterns in data.",
|
||||
"PyTorch is a popular deep learning framework.",
|
||||
"Natural language processing involves understanding text.",
|
||||
]
|
||||
self.agent = SearchAgent(self.corpus, embedding_dim=20)
|
||||
|
||||
def test_vocab_size(self):
|
||||
# Vocabulary should contain all unique words
|
||||
vocab_size = self.agent.get_vocab_size()
|
||||
# Count unique words manually
|
||||
unique_words = set()
|
||||
for doc in self.corpus:
|
||||
unique_words.update(doc.lower().split())
|
||||
self.assertEqual(vocab_size, len(unique_words))
|
||||
|
||||
def test_document_embeddings_shape(self):
|
||||
# Document embeddings should have shape (n_docs, dim)
|
||||
doc_emb = self.agent.doc_embeddings
|
||||
self.assertEqual(doc_emb.shape, (len(self.corpus), self.agent.embedding_dim))
|
||||
|
||||
def test_query_encoding_shape(self):
|
||||
query = "deep learning"
|
||||
vec = self.agent._encode_text(query)
|
||||
self.assertEqual(vec.shape, (self.agent.embedding_dim,))
|
||||
|
||||
def test_cosine_similarity(self):
|
||||
# Compute similarity between two identical vectors
|
||||
vec = self.agent._encode_text("deep learning")
|
||||
sims = self.agent._cosine_similarity(vec.unsqueeze(0), vec.unsqueeze(0))
|
||||
self.assertAlmostEqual(sims.item(), 1.0, places=5)
|
||||
|
||||
def test_search_ranking(self):
|
||||
# Query that matches second document
|
||||
results = self.agent.search("deep learning", top_k=2)
|
||||
# The first result should be the second document (index 1)
|
||||
self.assertEqual(results[0].doc_id, 1)
|
||||
self.assertGreater(results[0].score, results[1].score)
|
||||
|
||||
def test_unknown_words(self):
|
||||
# Query with unknown words should still return results
|
||||
results = self.agent.search("xyz abc", top_k=1)
|
||||
self.assertEqual(len(results), 1)
|
||||
self.assertIsInstance(results[0], Result)
|
||||
|
||||
def test_empty_query(self):
|
||||
# Empty query should return top documents based on zero vector
|
||||
results = self.agent.search("", top_k=3)
|
||||
self.assertEqual(len(results), 3)
|
||||
# Scores should be non‑negative
|
||||
for res in results:
|
||||
self.assertGreaterEqual(res.score, 0.0)
|
||||
class DummyAgent(Agent):
|
||||
def act(self, state):
|
||||
return state
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
def test_dummy_agent():
|
||||
agent = DummyAgent()
|
||||
assert agent.act(5) == 5
|
||||
assert agent.act("hello") == "hello"
|
||||
@@ -0,0 +1,20 @@
|
||||
import pytest
|
||||
|
||||
from src.index import search
|
||||
|
||||
|
||||
def test_search_returns_list():
|
||||
results = search("test")
|
||||
assert isinstance(results, list)
|
||||
assert len(results) == 5 # default limit
|
||||
|
||||
|
||||
def test_search_limit():
|
||||
results = search("example", limit=3)
|
||||
assert len(results) == 3
|
||||
assert results == ["example result 1", "example result 2", "example result 3"]
|
||||
|
||||
|
||||
def test_search_empty_query():
|
||||
with pytest.raises(ValueError):
|
||||
search("")
|
||||
@@ -0,0 +1,40 @@
|
||||
"""
|
||||
Unit tests for SearchAgent.
|
||||
"""
|
||||
|
||||
import torch
|
||||
import pytest
|
||||
from src.search_agent import SearchAgent, PolicyValueNet
|
||||
from src.utils import encode_state, get_actions, step
|
||||
|
||||
|
||||
def test_policy_value_net_forward():
|
||||
net = PolicyValueNet(input_dim=1, action_space=2)
|
||||
x = torch.tensor([[3.0]])
|
||||
policy, value = net(x)
|
||||
assert policy.shape == (1, 2)
|
||||
assert value.shape == (1, 1)
|
||||
|
||||
|
||||
def test_search_agent_action_selection():
|
||||
net = PolicyValueNet(input_dim=1, action_space=2)
|
||||
agent = SearchAgent(policy_value_net=net, max_depth=2)
|
||||
# Start from state 0; actions are 1 and 2
|
||||
action = agent.act(0)
|
||||
assert action in [1, 2]
|
||||
|
||||
|
||||
def test_search_agent_value_estimation():
|
||||
net = PolicyValueNet(input_dim=1, action_space=2)
|
||||
agent = SearchAgent(policy_value_net=net, max_depth=3)
|
||||
# For state 8, the optimal action is 10 (reward 1)
|
||||
action = agent.act(8)
|
||||
assert action == 10 or action == 9 # depending on policy, 10 is better
|
||||
|
||||
|
||||
def test_search_agent_terminal_state():
|
||||
net = PolicyValueNet(input_dim=1, action_space=2)
|
||||
agent = SearchAgent(policy_value_net=net, max_depth=1)
|
||||
# State 10 is terminal; agent should return 10
|
||||
action = agent.act(10)
|
||||
assert action == 10
|
||||
Reference in New Issue
Block a user