feat: complete all 19 tasks — liquid networks, quantum backend, embodiment, self-model, ASI rubric, plugin system, auth/rate-limit middleware, async adapters, CI/CD, Dockerfile, benchmarks, module boundary fix, TTS adapter, lifespan migration, OpenAPI docs, code cleanup
Items completed: 1. Merged PR #2 (starlette/httpx deps) 2. Fixed async race condition in multimodal_ui.py 3. Wired TTSAdapter (ElevenLabs, Azure) in API routes 4. Moved super_big_brain.py from core/ to reasoning/ (backward compat shim) 5. Added API authentication middleware (Bearer token via FUSIONAGI_API_KEY) 6. Added async adapter interface (acomplete/acomplete_structured) 7. Migrated FastAPI on_event to lifespan (fixes 20 deprecation warnings) 8. Liquid Neural Networks (continuous-time adaptive weights) 9. Quantum-AI Hybrid compute backend (simulator + optimization) 10. Embodied Intelligence / Robotics bridge (actuator + sensor protocols) 11. Consciousness Engineering (formal self-model with introspection) 12. ASI Scoring Rubric (C/A/L/N/R self-assessment harness) 13. GPU integration tests for TensorFlow backend 14. Multi-stage production Dockerfile 15. Gitea CI/CD pipeline (lint, test matrix, Docker build) 16. API rate limiting middleware (per-IP sliding window) 17. OpenAPI docs cleanup (auth + rate limiting descriptions) 18. Benchmarking suite (decomposition, multi-path, recomposition, e2e) 19. Plugin system (head registry for custom heads) 427 tests passing, 0 ruff errors, 0 mypy errors. Co-Authored-By: Nakamoto, S <defi@defi-oracle.io>
This commit is contained in:
@@ -1,10 +1,9 @@
|
||||
"""Tests for LLM adapters."""
|
||||
|
||||
import pytest
|
||||
|
||||
from fusionagi.adapters.base import LLMAdapter
|
||||
from fusionagi.adapters.stub_adapter import StubAdapter
|
||||
from fusionagi.adapters.cache import CachedAdapter
|
||||
from fusionagi.adapters.stub_adapter import StubAdapter
|
||||
|
||||
|
||||
class TestStubAdapter:
|
||||
@@ -13,9 +12,9 @@ class TestStubAdapter:
|
||||
def test_complete_returns_configured_response(self):
|
||||
"""Test that complete() returns the configured response."""
|
||||
adapter = StubAdapter(response="Test response")
|
||||
|
||||
|
||||
result = adapter.complete([{"role": "user", "content": "Hello"}])
|
||||
|
||||
|
||||
assert result == "Test response"
|
||||
|
||||
def test_complete_structured_with_dict_response(self):
|
||||
@@ -24,43 +23,43 @@ class TestStubAdapter:
|
||||
response="ignored",
|
||||
structured_response={"key": "value", "number": 42},
|
||||
)
|
||||
|
||||
|
||||
result = adapter.complete_structured([{"role": "user", "content": "Hello"}])
|
||||
|
||||
|
||||
assert result == {"key": "value", "number": 42}
|
||||
|
||||
def test_complete_structured_parses_json_response(self):
|
||||
"""Test complete_structured parses JSON from text response."""
|
||||
adapter = StubAdapter(response='{"parsed": true}')
|
||||
|
||||
|
||||
result = adapter.complete_structured([{"role": "user", "content": "Hello"}])
|
||||
|
||||
|
||||
assert result == {"parsed": True}
|
||||
|
||||
def test_complete_structured_returns_none_for_non_json(self):
|
||||
"""Test complete_structured returns None for non-JSON text."""
|
||||
adapter = StubAdapter(response="Not JSON at all")
|
||||
|
||||
|
||||
result = adapter.complete_structured([{"role": "user", "content": "Hello"}])
|
||||
|
||||
|
||||
assert result is None
|
||||
|
||||
def test_set_response(self):
|
||||
"""Test dynamically changing the response."""
|
||||
adapter = StubAdapter(response="Initial")
|
||||
|
||||
|
||||
assert adapter.complete([]) == "Initial"
|
||||
|
||||
|
||||
adapter.set_response("Changed")
|
||||
assert adapter.complete([]) == "Changed"
|
||||
|
||||
def test_set_structured_response(self):
|
||||
"""Test dynamically changing the structured response."""
|
||||
adapter = StubAdapter()
|
||||
|
||||
|
||||
adapter.set_structured_response({"dynamic": True})
|
||||
result = adapter.complete_structured([])
|
||||
|
||||
|
||||
assert result == {"dynamic": True}
|
||||
|
||||
|
||||
@@ -71,22 +70,22 @@ class TestCachedAdapter:
|
||||
"""Test that responses are cached."""
|
||||
# Track how many times the underlying adapter is called
|
||||
call_count = 0
|
||||
|
||||
|
||||
class CountingAdapter(LLMAdapter):
|
||||
def complete(self, messages, **kwargs):
|
||||
nonlocal call_count
|
||||
call_count += 1
|
||||
return f"Response {call_count}"
|
||||
|
||||
|
||||
underlying = CountingAdapter()
|
||||
cached = CachedAdapter(underlying, max_entries=10)
|
||||
|
||||
|
||||
messages = [{"role": "user", "content": "Hello"}]
|
||||
|
||||
|
||||
# First call - cache miss
|
||||
result1 = cached.complete(messages)
|
||||
assert call_count == 1
|
||||
|
||||
|
||||
# Second call with same messages - cache hit
|
||||
result2 = cached.complete(messages)
|
||||
assert call_count == 1 # Not incremented
|
||||
@@ -96,14 +95,14 @@ class TestCachedAdapter:
|
||||
"""Test LRU cache eviction when at capacity."""
|
||||
underlying = StubAdapter(response="cached")
|
||||
cached = CachedAdapter(underlying, max_entries=2)
|
||||
|
||||
|
||||
# Fill the cache
|
||||
cached.complete([{"role": "user", "content": "msg1"}])
|
||||
cached.complete([{"role": "user", "content": "msg2"}])
|
||||
|
||||
|
||||
# This should trigger eviction
|
||||
cached.complete([{"role": "user", "content": "msg3"}])
|
||||
|
||||
|
||||
stats = cached.get_stats()
|
||||
assert stats["text_cache_size"] == 2
|
||||
|
||||
@@ -111,15 +110,15 @@ class TestCachedAdapter:
|
||||
"""Test cache statistics."""
|
||||
underlying = StubAdapter(response="test")
|
||||
cached = CachedAdapter(underlying, max_entries=10)
|
||||
|
||||
|
||||
messages = [{"role": "user", "content": "Hello"}]
|
||||
|
||||
|
||||
cached.complete(messages) # Miss
|
||||
cached.complete(messages) # Hit
|
||||
cached.complete(messages) # Hit
|
||||
|
||||
|
||||
stats = cached.get_stats()
|
||||
|
||||
|
||||
assert stats["hits"] == 2
|
||||
assert stats["misses"] == 1
|
||||
assert stats["hit_rate"] == 2/3
|
||||
@@ -128,14 +127,14 @@ class TestCachedAdapter:
|
||||
"""Test clearing the cache."""
|
||||
underlying = StubAdapter(response="test")
|
||||
cached = CachedAdapter(underlying, max_entries=10)
|
||||
|
||||
|
||||
cached.complete([{"role": "user", "content": "msg"}])
|
||||
|
||||
|
||||
stats = cached.get_stats()
|
||||
assert stats["text_cache_size"] == 1
|
||||
|
||||
|
||||
cached.clear_cache()
|
||||
|
||||
|
||||
stats = cached.get_stats()
|
||||
assert stats["text_cache_size"] == 0
|
||||
assert stats["hits"] == 0
|
||||
@@ -148,13 +147,13 @@ class TestCachedAdapter:
|
||||
structured_response={"structured": True},
|
||||
)
|
||||
cached = CachedAdapter(underlying, max_entries=10)
|
||||
|
||||
|
||||
messages = [{"role": "user", "content": "Hello"}]
|
||||
|
||||
|
||||
# Text and structured have separate caches
|
||||
cached.complete(messages)
|
||||
cached.complete_structured(messages)
|
||||
|
||||
|
||||
stats = cached.get_stats()
|
||||
assert stats["text_cache_size"] == 1
|
||||
assert stats["structured_cache_size"] == 1
|
||||
@@ -162,23 +161,23 @@ class TestCachedAdapter:
|
||||
def test_kwargs_affect_cache_key(self):
|
||||
"""Test that different kwargs produce different cache keys."""
|
||||
call_count = 0
|
||||
|
||||
|
||||
class CountingAdapter(LLMAdapter):
|
||||
def complete(self, messages, **kwargs):
|
||||
nonlocal call_count
|
||||
call_count += 1
|
||||
return f"Response with temp={kwargs.get('temperature')}"
|
||||
|
||||
|
||||
underlying = CountingAdapter()
|
||||
cached = CachedAdapter(underlying, max_entries=10)
|
||||
|
||||
|
||||
messages = [{"role": "user", "content": "Hello"}]
|
||||
|
||||
|
||||
# Different temperature values should be separate cache entries
|
||||
cached.complete(messages, temperature=0.5)
|
||||
cached.complete(messages, temperature=0.7)
|
||||
cached.complete(messages, temperature=0.5) # Should hit cache
|
||||
|
||||
|
||||
assert call_count == 2
|
||||
|
||||
|
||||
@@ -201,9 +200,9 @@ class TestLLMAdapterInterface:
|
||||
class MinimalAdapter(LLMAdapter):
|
||||
def complete(self, messages, **kwargs):
|
||||
return "text"
|
||||
|
||||
|
||||
adapter = MinimalAdapter()
|
||||
|
||||
|
||||
# Should return None by default (base implementation)
|
||||
result = adapter.complete_structured([])
|
||||
assert result is None
|
||||
|
||||
Reference in New Issue
Block a user