Skip to content

Commit a472d78

Browse files
committed
examples(semantic-cache): address follow-up review
- Query with alpha=1.0 (pure semantic) so the score reflects meaning, matching the 'semantic similarity' threshold wording. - Guard optional QueryResultDocumentInfo.metadata (use (metadata or {}).get()). - Guard nullable OpenAI message.content. - Use a unique session name per run so the demo is deterministic (clean MISS->HIT); documented the stable-name + push_index() path for real persistence.
1 parent 2155b15 commit a472d78

1 file changed

Lines changed: 14 additions & 11 deletions

File tree

moss-live-labs/examples/semantic-cache/semantic_cache.py

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import os
1515
import sys
1616
import time
17+
import uuid
1718

1819
from dotenv import load_dotenv
1920
from openai import AsyncOpenAI
@@ -35,7 +36,7 @@ def _require(name: str) -> str:
3536
MOSS_PROJECT_KEY = _require("MOSS_PROJECT_KEY")
3637
_require("OPENAI_API_KEY") # read by AsyncOpenAI from the environment
3738

38-
# cosine similarity above which a cached answer is "close enough" to reuse.
39+
# semantic similarity above which a cached answer is "close enough" to reuse.
3940
# too low -> you answer questions people didn't quite ask; too high -> you miss.
4041
THRESHOLD = 0.92
4142

@@ -50,10 +51,12 @@ def __init__(self, store):
5051
self.store = store
5152

5253
async def ask(self, question: str) -> tuple[str, bool]:
53-
# 1. look for the closest question we've already answered
54-
hit = await self.store.query(question, QueryOptions(top_k=1))
54+
# 1. look for the closest question we've already answered.
55+
# alpha=1.0 -> pure semantic (embedding) match, so the score reflects
56+
# meaning rather than keyword overlap.
57+
hit = await self.store.query(question, QueryOptions(top_k=1, alpha=1.0))
5558
if hit.docs and hit.docs[0].score >= THRESHOLD:
56-
answer = hit.docs[0].metadata.get("answer")
59+
answer = (hit.docs[0].metadata or {}).get("answer")
5760
if answer is not None:
5861
return answer, True # cache hit — no LLM call
5962

@@ -62,7 +65,7 @@ async def ask(self, question: str) -> tuple[str, bool]:
6265
model="gpt-4o-mini",
6366
messages=[{"role": "user", "content": question}],
6467
)
65-
answer = resp.choices[0].message.content
68+
answer = resp.choices[0].message.content or ""
6669

6770
# 3. remember it so any wording of it is instant next time
6871
await self.store.add_docs(
@@ -72,12 +75,12 @@ async def ask(self, question: str) -> tuple[str, bool]:
7275

7376

7477
async def main():
75-
# A Moss session is the cache store. It holds the entries in memory for this
76-
# run, so the demo is deterministic: the first question is a MISS and its
77-
# paraphrase is a HIT. To make the cache persist across runs and processes,
78-
# call `await store.push_index()` to upload it as a cloud index (it will then
79-
# auto-load by name on the next run).
80-
store = await moss.session(index_name="qa-cache")
78+
# A Moss session is the cache store. We use a unique name per run so the demo
79+
# always starts empty and shows a clean MISS -> HIT (a session auto-loads an
80+
# existing cloud index of the same name, which would otherwise make the first
81+
# question a HIT). In production, use a stable name and call
82+
# `await store.push_index()` to persist the cache across runs and processes.
83+
store = await moss.session(index_name=f"qa-cache-demo-{uuid.uuid4().hex[:8]}")
8184
cache = SemanticCache(store)
8285

8386
# the 2nd question means the same as the 1st, phrased differently -> cache hit

0 commit comments

Comments
 (0)