AI Engineering Academy · Pelajaran

Pencaching Semantik dengan Embedding

Bina cache semantik yang mendapatkan respons tersimpan untuk pertanyaan yang serupa dari segi semantik tetapi tidak sepadan sepenuhnya, dengan membandingkan embedding pertanyaan dengan cache embedding permintaan terdahulu.

Pelajaran 2 daripada 413 langkah

Pencaching Semantik dengan Embedding ialah pelajaran AI Engineering Academy percuma di CoddyKit. Ini ialah pelajaran 2 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran AI Engineering Academy, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus AI Engineering Academy merangkumi sejumlah 4 pelajaran.

Had Pencachean Tepat

Pencachean tepat hanya membantu apabila pengguna menghantar permintaan yang serupa bait demi bait. Dalam realiti, pengguna menyatakan soalan yang sama dengan cara berbeza: 'Bagaimanakah saya membatalkan langganan saya?', 'Apakah proses untuk berhenti melanggan?' dan 'Bolehkah saya menghentikan pelan saya?' semuanya bermaksud soalan yang sama tetapi menghasilkan kunci cache yang berbeza. Pencachean tepat terlepas semua variasi ini. Pencachean semantik menyelesaikan masalah ini dengan memadankan pertanyaan yang serupa, bukannya yang seiras, lalu meningkatkan kadar cache hit dengan ketara.

Cara Pencachean Semantik Berfungsi

Cache semantik menyimpan embedding bagi setiap pertanyaan yang dicache bersama-sama respons cache. Apabila pertanyaan baharu tiba, hasilkan embeddingnya dan cari dalam cache pertanyaan terdahulu yang mempunyai kesamaan kosinus yang tinggi. Jika pertanyaan cache yang paling hampir melebihi ambang kesamaan (biasanya 0.95+), kembalikan respons cachenya. Jika tiada padanan ditemui, panggil LLM, simpan respons baharu dan tambahkan embedding pertanyaan baharu itu pada indeks cache untuk carian akan datang.

# Semantic cache flow
# 1. New query arrives: 'How do I cancel my subscription?'
# 2. Embed it: embed_query = embed('How do I cancel my subscription?')
# 3. Search cache index for nearest cached query embedding
# 4. Find cached: 'What is the process to unsubscribe?' (similarity=0.97)
# 5. 0.97 >= threshold (0.95) → cache HIT, return cached response
# 6. If 0.82 < threshold → cache MISS, call LLM, cache result, add embedding to index

Cache Semantik Dalam Memori dengan NumPy

Untuk aplikasi kecil atau prototaip, laksanakan pencachean semantik dalam memori menggunakan NumPy bagi mengira kesamaan kosinus. Simpan embedding pertanyaan yang dicache dalam tatasusunan 2D dan respons dalam senarai selari. Bagi setiap pertanyaan baharu, kira kesamaan kosinus antara embedding baharu dengan semua embedding yang dicache, kemudian kembalikan padanan paling hampir jika nilainya melebihi ambang.

import numpy as np
from openai import OpenAI

client = OpenAI()

class InMemorySemanticCache:
    def __init__(self, threshold: float = 0.95):
        self.threshold = threshold
        self.embeddings = []    # list of np.ndarray
        self.responses = []     # list of str
        self.queries = []       # list of str (for inspection)

    def _embed(self, text: str) -> np.ndarray:
        resp = client.embeddings.create(model='text-embedding-3-small', input=text)
        return np.array(resp.data[0].embedding)

    def get(self, query: str) -> str | None:
        if not self.embeddings:
            return None
        q_emb = self._embed(query)
        cache_matrix = np.array(self.embeddings)
        # Cosine similarity: dot product of normalized vectors
        norms = np.linalg.norm(cache_matrix, axis=1)
        q_norm = np.linalg.norm(q_emb)
        sims = (cache_matrix @ q_emb) / (norms * q_norm + 1e-8)
        best_idx = int(np.argmax(sims))
        if sims[best_idx] >= self.threshold:
            print(f'[SEMANTIC HIT] sim={sims[best_idx]:.3f} matched: {self.queries[best_idx]!r}')
            return self.responses[best_idx]
        return None

    def set(self, query: str, response: str):
        emb = self._embed(query)
        self.embeddings.append(emb)
        self.responses.append(response)
        self.queries.append(query)

Cache Semantik dengan Redis dan Pinecone

Untuk caching semantik dalam persekitaran produksi, simpan embedding pertanyaan dalam pangkalan data vektor bagi carian jiran terdekat anggaran yang pantas, dan simpan respons dalam Redis menggunakan ID unik sebagai kunci. Apabila pertanyaan baharu diterima, cari pertanyaan tercache yang paling hampir dalam pangkalan data vektor, dapatkan semula respons daripada Redis menggunakan ID dalam metadata vektor, lalu kembalikannya — semuanya tanpa memanggil LLM.

import redis
from pinecone import Pinecone
import hashlib

r = redis.Redis(decode_responses=True)
pc = Pinecone(api_key='YOUR_KEY')
index = pc.Index('semantic-cache')

SIMILARITY_THRESHOLD = 0.95

def semantic_cache_get(query: str) -> str | None:
    q_emb = embed(query)  # from earlier lesson
    results = index.query(vector=q_emb, top_k=1, include_metadata=True)
    if not results.matches:
        return None
    best = results.matches[0]
    if best.score >= SIMILARITY_THRESHOLD:
        response_key = best.metadata.get('response_key')
        return r.get(response_key)
    return None

def semantic_cache_set(query: str, response: str):
    q_emb = embed(query)
    entry_id = hashlib.sha256(query.encode()).hexdigest()[:16]
    response_key = f'sem_cache_resp:{entry_id}'
    r.setex(response_key, 86400, response)  # 24h TTL
    index.upsert(vectors=[{
        'id': entry_id,
        'values': q_emb,
        'metadata': {'query': query[:200], 'response_key': response_key},
    }])

GPTCache: Cache Semantik Sedia Digunakan

GPTCache ialah pustaka sumber terbuka yang melaksanakan caching semantik untuk aplikasi LLM. Pustaka ini membalut klien OpenAI, membenamkan pertanyaan secara automatik, menyemak cache kesamaan vektor, dan menggunakan API sebenar sebagai sandaran apabila cache tidak memberikan hasil. Pustaka ini menyokong pelbagai stor vektor (FAISS, Milvus, Redis) dan pelbagai model embedding secara terus, menjadikannya cara pantas untuk menambahkan caching semantik pada aplikasi sedia ada.

# pip install gptcache
from gptcache import cache
from gptcache.adapter import openai
from gptcache.embedding import OpenAI as EmbeddingOpenAI
from gptcache.manager import CacheBase, VectorBase, get_data_manager
from gptcache.similarity_evaluation.distance import SearchDistanceEvaluation

# Configure GPTCache with FAISS vector store
cache.init(
    embedding_func=EmbeddingOpenAI().to_embeddings,
    data_manager=get_data_manager(
        CacheBase('sqlite'),
        VectorBase('faiss', dimension=1536),
    ),
    similarity_evaluation=SearchDistanceEvaluation(),
)

# Now use the wrapped openai client — caching is transparent
response = openai.ChatCompletion.create(
    model='gpt-4o-mini',
    messages=[{'role': 'user', 'content': 'What is RAG?'}],
)

Memilih Ambang Kesamaan

Ambang kesamaan ialah hiperparameter yang paling penting untuk caching semantik. Jika terlalu tinggi (0.99+), kebanyakan variasi parafrasa tidak akan ditemukan. Jika terlalu rendah (0.85-), jawapan tercache yang salah akan dikembalikan untuk pertanyaan yang berbeza tetapi kelihatan serupa. Sahkan ambang anda secara empirikal dengan mengambil sampel pasangan pertanyaan dan menyemak sama ada pertanyaan yang melebihi ambang itu benar-benar mempunyai jawapan yang sama. Nilai lazim: 0.92-0.97 untuk soal jawab fakta, dan 0.98+ untuk penjanaan kod apabila perbezaan kecil sangat penting.

def validate_threshold(cache, query_pairs_with_labels):
    '''
    query_pairs_with_labels: list of (query1, query2, should_match: bool)
    '''
    true_pos = true_neg = false_pos = false_neg = 0
    for q1, q2, should_match in query_pairs_with_labels:
        e1, e2 = embed(q1), embed(q2)
        sim = cosine_similarity(e1, e2)
        matched = sim >= cache.threshold
        if should_match and matched: true_pos += 1
        elif not should_match and not matched: true_neg += 1
        elif not should_match and matched: false_pos += 1
        else: false_neg += 1
    precision = true_pos / (true_pos + false_pos) if (true_pos + false_pos) else 0
    recall = true_pos / (true_pos + false_neg) if (true_pos + false_neg) else 0
    print(f'Precision: {precision:.3f}, Recall: {recall:.3f}')

Skop Cache Semantik: Gesaan Sistem Penting

Perincian kritikal: caching semantik mesti mengambil kira gesaan sistem. Dua pertanyaan pengguna yang sama boleh menghasilkan jawapan berbeza jika gesaan sistem berbeza (persona berbeza, pangkalan pengetahuan berbeza, format respons berbeza). Sentiasa sertakan gesaan sistem dalam input embedding atau cipta ruang nama cache yang berasingan bagi setiap gesaan sistem. Corak yang kemas ialah mencincang gesaan sistem dan menggunakannya sebagai awalan ruang nama cache.

import hashlib

def make_semantic_cache_namespace(system_prompt: str) -> str:
    return 'sc:' + hashlib.md5(system_prompt.encode()).hexdigest()[:8]

def semantic_cache_get_namespaced(system_prompt: str, user_query: str) -> str | None:
    namespace = make_semantic_cache_namespace(system_prompt)
    q_emb = embed(user_query)
    # Search only within this namespace
    results = index.query(
        vector=q_emb,
        top_k=1,
        filter={'namespace': namespace},
        include_metadata=True,
    )
    if results.matches and results.matches[0].score >= SIMILARITY_THRESHOLD:
        return r.get(results.matches[0].metadata['response_key'])
    return None

Analisis Kadar Cache Semantik Berjaya

Selepas menggunakan caching semantik, analisis kadar kejayaan mengikut kelompok pertanyaan. Gunakan embedding pertanyaan tercache itu sendiri — kelompokkan embedding tersebut dengan K-means dan kira kadar kejayaan bagi setiap kelompok. Kelompok dengan kadar kejayaan tinggi mewakili tema soalan umum yang paling banyak mendapat manfaat daripada caching. Kelompok dengan kadar kejayaan rendah yang mengandungi pertanyaan unik dan pelbagai mungkin langsung tidak mendapat manfaat daripada caching, dan boleh dikecualikan daripada cache untuk mengurangkan saiz indeks serta kos embedding.

from sklearn.cluster import KMeans
import numpy as np

def analyze_cache_clusters(cache, n_clusters=10):
    if len(cache.embeddings) < n_clusters:
        print('Not enough cache entries to cluster')
        return

    matrix = np.array(cache.embeddings)
    kmeans = KMeans(n_clusters=n_clusters, n_init=10, random_state=42)
    labels = kmeans.fit_predict(matrix)

    from collections import Counter
    cluster_sizes = Counter(labels)
    print('Query clusters by size:')
    for cluster_id, count in cluster_sizes.most_common():
        representative = cache.queries[labels.tolist().index(cluster_id)]
        print(f'  Cluster {cluster_id}: {count} queries, e.g. {representative!r}')

Pertimbangan Keselamatan Cache Semantik

Caching semantik memperkenalkan risiko privasi: jika pengguna A mengemukakan soalan sensitif, responsnya mungkin dikembalikan kepada pengguna B yang mengemukakan soalan serupa. Hal ini boleh diterima untuk pangkalan pengetahuan awam, tetapi tidak untuk aplikasi yang mempunyai data khusus pengguna atau kandungan sensitif. Gunakan pengasingan ruang nama yang ketat bagi setiap pengguna atau organisasi, dan pertimbangkan untuk mengecualikan sepenuhnya daripada cache pertanyaan yang sepadan dengan corak seperti maklumat peribadi.

import re

PII_PATTERNS = [
    r'\b\d{3}[-.]?\d{3}[-.]?\d{4}\b',   # phone numbers
    r'\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b',  # emails
    r'\b\d{9}\b',                           # SSN-like
]

def should_cache(query: str) -> bool:
    for pattern in PII_PATTERNS:
        if re.search(pattern, query, re.IGNORECASE):
            return False  # do not cache queries with PII
    return True

def secure_semantic_completion(user_id: str, query: str) -> str:
    if should_cache(query):
        cached = semantic_cache_get_namespaced(f'user:{user_id}', query)
        if cached:
            return cached
    result = call_llm_api(query)  # actual API call
    if should_cache(query):
        semantic_cache_set_namespaced(f'user:{user_id}', query, result)
    return result

Menggabungkan Caching Tepat dan Semantik

Strategi caching yang paling cekap menggunakan caching tepat dan semantik dalam hierarki dua peringkat. Semak cache tepat dahulu (paling pantas, tanpa kos embedding) dan kembalikan hasil serta-merta jika berjaya. Jika cache tepat tidak berjaya, semak cache semantik (memerlukan satu panggilan API embedding). Jika cache semantik juga tidak berjaya, panggil LLM. Susunan ini meminimumkan kedua-dua kependaman dan kos bagi setiap permintaan.

async def two_tier_cached_completion(messages: list[dict], model: str = 'gpt-4o-mini') -> str:
    user_query = messages[-1].get('content', '')
    system_prompt = messages[0].get('content', '') if messages and messages[0]['role'] == 'system' else ''

    # Tier 1: exact cache (instant, free)
    exact_key = make_cache_key(messages, model, temperature=0.0)
    exact_cached = await async_r.get(exact_key)
    if exact_cached:
        return json.loads(exact_cached)

    # Tier 2: semantic cache (one embedding call ~5ms)
    sem_result = semantic_cache_get_namespaced(system_prompt, user_query)
    if sem_result:
        # Backfill exact cache to avoid embedding next time
        await async_r.setex(exact_key, 3600, json.dumps(sem_result))
        return sem_result

    # Tier 3: actual LLM call
    response = await async_client.chat.completions.create(
        model=model, messages=messages, temperature=0.0
    )
    result = response.choices[0].message.content
    await async_r.setex(exact_key, 3600, json.dumps(result))
    semantic_cache_set_namespaced(system_prompt, user_query, result)
    return result

Pemanasan Cache untuk Permulaan Sejuk

Cache semantik yang baharu tidak memberikan sebarang manfaat sehingga diisi. Bagi aplikasi dengan corak trafik yang boleh dijangka, panaskan cache terlebih dahulu semasa permulaan dengan membenamkan dan mencache respons untuk soalan yang paling kerap ditanya berdasarkan log pertanyaan sejarah anda. Ini menghapuskan tempoh permulaan sejuk apabila setiap pengguna dalam beberapa jam pertama operasi mengalami cache tidak berjaya dan menanggung kos API penuh.

async def warm_semantic_cache(faq_list: list[dict], system_prompt: str):
    print(f'Warming cache with {len(faq_list)} FAQ entries...')
    for entry in faq_list:
        cached = semantic_cache_get_namespaced(system_prompt, entry['question'])
        if cached:
            print(f'  Already cached: {entry["question"][:50]}')
            continue
        # Generate and cache the response
        response = await async_client.chat.completions.create(
            model='gpt-4o-mini',
            messages=[
                {'role': 'system', 'content': system_prompt},
                {'role': 'user', 'content': entry['question']},
            ],
            temperature=0.0,
        )
        answer = response.choices[0].message.content
        semantic_cache_set_namespaced(system_prompt, entry['question'], answer)
        print(f'  Cached: {entry["question"][:50]}')
    print('Cache warming complete')

Semakan Pantas

Uji pemahaman anda tentang caching semantik daripada pelajaran ini.

Imbas Kembali Pelajaran

Dalam pelajaran ini anda telah mempelajari bahawa: caching semantik memadankan pertanyaan yang serupa tetapi tidak seiras dengan membandingkan embedding pertanyaan dengan stor vektor yang mengandungi embedding pertanyaan tercache, ambang kesamaan mengawal pertukaran antara kadar kejayaan dan ketepatan jawapan, manakala penamaan ruang mengikut gesaan sistem menghalang cache daripada berjaya secara salah merentas konteks. Seni bina dua peringkat yang menyemak cache tepat sebelum cache semantik meminimumkan kedua-dua kependaman dan kos embedding. Seterusnya, kita akan memanfaatkan caching awalan gesaan terbina dalam OpenAI.

Percuma untuk bermula

Pelajari Python dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
30
Pelajaran
120

Soalan Lazim

Adakah pelajaran “Pencaching Semantik dengan Embedding” percuma?

Ya — teks penuh “Pencaching Semantik dengan Embedding” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus AI Engineering Academy, tingkat taraf kepada CoddyKit PRO. Kursus AI Engineering Academy merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “Pencaching Semantik dengan Embedding”?

Bina cache semantik yang mendapatkan respons tersimpan untuk pertanyaan yang serupa dari segi semantik tetapi tidak sepadan sepenuhnya, dengan membandingkan embedding pertanyaan dengan cache embeddin… Anda berlatih AI Engineering Academy menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan AI Engineering Academy?

Tiada pengalaman terdahulu diperlukan. Pembelajaran AI Engineering Academy di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 2 daripada 4.

Berapa lamakah pelajaran “Pencaching Semantik dengan Embedding” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran AI Engineering Academy ini?

Ya. Setiap pelajaran AI Engineering Academy menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Pencaching Tepat dengan Redis
  2. Pencaching Semantik dengan Embedding
  3. Pencaching Awalan Gesaan OpenAI
  4. Pengumpulan Kelompok, Penghalaan Model dan Papan Pemuka Kos
← Kembali ke AI Engineering Academy