Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 2026-01-29 - Default DB Path in Tests
**Learning:** `AdaptiveMemory` defaults to the production database path in `__init__`. Running tests (like `test_ananta_quick.py`) without overriding `db_path` writes to the production `memory/data/adaptive_memory.db`, causing accidental binary file modifications in git.
**Action:** When writing tests involving `AdaptiveMemory`, always pass a temporary `db_path` or mock it. When running existing tests, be aware they might touch production data.
25 changes: 14 additions & 11 deletions core/ollama_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ def __init__(self, model: str = None, base_url: Optional[str] = None):
self.generate_url = f"{self.base_url}/api/generate"
self.chat_url = f"{self.base_url}/api/chat"

# Initialize persistent session for performance
# ⚑ Bolt Optimization: Reuse TCP connection
self.session = requests.Session()

# Configure GPU settings
import torch
self.gpu_available = torch.cuda.is_available()
Expand Down Expand Up @@ -60,7 +64,7 @@ def generate_with_system(
"repeat_penalty": self.gpu_settings["repeat_penalty"],
}

resp = requests.post(
resp = self.session.post(
self.chat_url,
json={
"model": self.model,
Expand Down Expand Up @@ -109,7 +113,7 @@ def generate(self, prompt: str, max_tokens: int = None, temperature: float = 0.2
retries = 3
for attempt in range(retries):
try:
resp = requests.post(
resp = self.session.post(
self.generate_url,
json={
"model": self.model,
Expand Down Expand Up @@ -167,7 +171,7 @@ def stream_with_system(
{"role": "user", "content": user_message}
]

resp = requests.post(
resp = self.session.post(
self.chat_url,
json={
"model": self.model,
Expand Down Expand Up @@ -207,14 +211,14 @@ def stream(self, prompt: str, max_tokens: int = None, temperature: float = 0.2)
max_tokens = min(max(max_tokens, 256), 1024)

# Configure keepalive and chunk size for smoother streaming
session = requests.Session()
session.headers.update({
# Bolt Optimization: Use shared session but add specific headers
headers = {
'Connection': 'keep-alive',
'Accept': 'text/event-stream',
'Cache-Control': 'no-cache'
})
}

resp = session.post(
resp = self.session.post(
self.generate_url,
json={
"model": self.model,
Expand All @@ -232,6 +236,7 @@ def stream(self, prompt: str, max_tokens: int = None, temperature: float = 0.2)
},
"stream": True
},
headers=headers,
stream=True,
timeout=180
)
Expand All @@ -257,8 +262,7 @@ def stream(self, prompt: str, max_tokens: int = None, temperature: float = 0.2)

except Exception as e:
yield f"ERROR: {e}"
finally:
session.close()
# Session is persistent, no need to close

def chat(
self,
Expand All @@ -267,7 +271,7 @@ def chat(
temperature: float = 0.3
) -> str:
try:
resp = requests.post(
resp = self.session.post(
self.chat_url,
json={
"model": self.model,
Expand All @@ -289,4 +293,3 @@ def chat(
return "ERROR: No response from model"
except Exception as e:
return f"ERROR: {e}"

58 changes: 58 additions & 0 deletions tests/test_ollama_session.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import unittest
from unittest.mock import patch, MagicMock
import sys
import os

# Mock torch before importing core.ollama_client
sys.modules['torch'] = MagicMock()

# Add project root to path
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

from core.ollama_client import OllamaClient

class TestOllamaSession(unittest.TestCase):
def setUp(self):
# Patch requests
self.requests_patcher = patch('core.ollama_client.requests')
self.mock_requests = self.requests_patcher.start()

# Setup mock session
self.mock_session = MagicMock()
self.mock_requests.Session.return_value = self.mock_session

# Setup mock response
self.mock_response = MagicMock()
self.mock_response.json.return_value = {"message": {"content": "Test response"}, "response": "Test response", "done": True}
self.mock_response.iter_lines.return_value = [b'{"response": "Test chunk", "done": false}', b'{"done": true}']
self.mock_session.post.return_value = self.mock_response
self.mock_requests.post.return_value = self.mock_response

def tearDown(self):
self.requests_patcher.stop()

def test_session_initialized(self):
"""Test that self.session is initialized"""
client = OllamaClient()
self.assertTrue(hasattr(client, 'session'), "OllamaClient should have a 'session' attribute")
self.assertEqual(client.session, self.mock_session, "client.session should be the mock session")

def test_chat_uses_session(self):
"""Test that chat uses the session.post"""
client = OllamaClient()
client.chat([{"role": "user", "content": "Hello"}])

# Should call session.post, NOT requests.post
self.mock_session.post.assert_called()
self.mock_requests.post.assert_not_called()

def test_generate_uses_session(self):
"""Test that generate uses the session.post"""
client = OllamaClient()
client.generate("Hello")

self.mock_session.post.assert_called()
self.mock_requests.post.assert_not_called()

if __name__ == '__main__':
unittest.main()