Summary
Add a SemanticCache component that matches chat requests by vector similarity, backed by an existing RagProviderInterface (ADR-0045) for storage/retrieval and a ProviderInterface for query embeddings. See ADR-0049.
Design
SemanticCache is a standalone class, not a CacheInterface implementation, because the lookup model differs fundamentally (text similarity vs. string-key equality). See ADR-0049 "Alternatives Considered".
class SemanticCache {
public function __construct(
RagProviderInterface $store,
ProviderInterface $embedder,
) {}
public function lookup(string $query, SemanticCacheConfig $config): ?ChatResponse {}
public function store(string $query, ChatResponse $response, SemanticCacheConfig $config): void {}
public function clear(): void {}
}
lookup()
- Call
$store->retrieve($query, topK: 1).
- If no result or
result.score < $config->getThreshold() → return null (miss).
- Reconstruct
ChatResponse from result.getMetadata()['cached_response'] via ChatResponse::fromArray().
store()
- Serialize the response via
ChatResponse::toArray().
$store->ingest($query, ['cached_response' => $arr, 'model' => ..., 'provider' => ..., 'created_at' => time()]).
Dependencies
Acceptance Criteria
References
- ADR-0049: AI: Semantic Response Caching
- ADR-0045: RagProviderInterface
Summary
Add a
SemanticCachecomponent that matches chat requests by vector similarity, backed by an existingRagProviderInterface(ADR-0045) for storage/retrieval and aProviderInterfacefor query embeddings. See ADR-0049.Design
SemanticCacheis a standalone class, not aCacheInterfaceimplementation, because the lookup model differs fundamentally (text similarity vs. string-key equality). See ADR-0049 "Alternatives Considered".lookup()
$store->retrieve($query, topK: 1).result.score < $config->getThreshold()→ returnnull(miss).ChatResponsefromresult.getMetadata()['cached_response']viaChatResponse::fromArray().store()
ChatResponse::toArray().$store->ingest($query, ['cached_response' => $arr, 'model' => ..., 'provider' => ..., 'created_at' => time()]).Dependencies
lookup()/store()needtoArray()/fromArray().RagProviderInterface+RetrievalResult(already providescore+ freeformmetadata, verified sufficient — no RAG interface changes needed).Acceptance Criteria
SemanticCacheclass withlookup(),store(),clear()RetrievalResult::getScore()RagProviderInterfacecovering: hit above threshold, miss below threshold, empty store, round-trip of stored responsecomposer testgreenReferences