

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

# Multi-turn caching percakapan
<a name="semantic-caching-multi-turn"></a>

Untuk aplikasi dengan percakapan multi-putaran, pesan pengguna yang sama dapat berarti hal yang berbeda tergantung pada konteksnya. Misalnya, “Ceritakan lebih banyak” dalam percakapan tentang Valkey berarti sesuatu yang berbeda dari “Ceritakan lebih banyak” dalam percakapan tentang Python.

## Tantangannya
<a name="semantic-caching-multi-turn-challenge"></a>

Single-prompt caching berfungsi dengan baik untuk kueri tanpa kewarganegaraan. Dalam percakapan multi-putaran, Anda harus menyimpan konteks percakapan lengkap, bukan hanya pesan terakhir:

```
# "Tell me more" means nothing without context
# Conversation A: "What is Valkey?" -> "Tell me more"  (about Valkey)
# Conversation B: "What is Python?" -> "Tell me more"  (about Python)
```

## Strategi: kunci cache sadar konteks
<a name="semantic-caching-context-aware-keys"></a>

Alih-alih hanya menyematkan pesan pengguna terakhir, sematkan ringkasan konteks percakapan lengkap. Dengan cara ini, pertanyaan tindak lanjut serupa dalam alur percakapan serupa dapat menggunakan kembali jawaban yang di-cache.

```
def build_context_string(messages: list) -> str:
    """Build a cacheable context string from conversation messages."""
    # Use last 3 turns (6 messages: user + assistant pairs)
    recent = messages[-6:]
    parts = []
    for msg in recent:
        role = msg["role"]
        content = msg["content"][:200]  # Truncate long messages
        parts.append(f"{role}: {content}")
    return " | ".join(parts)
```

## Per-user isolasi cache dengan filter TAG
<a name="semantic-caching-tag-filters"></a>

Gunakan kolom TAG untuk mengisolasi percakapan yang di-cache menurut pengguna, sesi, atau dimensi lainnya. Ini mencegah percakapan cache satu pengguna dikembalikan untuk pengguna lain:

```
# Create index with TAG field for per-user isolation
valkey_client.execute_command(
    "FT.CREATE", "conv_cache_idx",
    "SCHEMA",
    "context_summary", "TEXT",
    "response", "TEXT",
    "user_id", "TAG",
    "turn_count", "NUMERIC",
    "embedding", "VECTOR", "HNSW", "6",
    "TYPE", "FLOAT32",
    "DIM", "1024",
    "DISTANCE_METRIC", "COSINE",
)
```

Cari dengan penyaringan hibrida (TAG \+ KNN):

```
def lookup_conversation_cache(messages: list, user_id: str, threshold: float = 0.12):
    """Search cache for similar conversation contexts, scoped to a user.

    Note: FT.SEARCH with COSINE distance returns a distance score where
    0 = identical and 2 = opposite. A lower score means higher similarity.
    The threshold here is a maximum distance: only return results closer
    than this value.
    """
    context = build_context_string(messages)
    query_vec = get_embedding(context)

    # Hybrid search: filter by user_id TAG + KNN on context embedding
    results = valkey_client.execute_command(
        "FT.SEARCH", "conv_cache_idx",
        f"@user_id:{{{user_id}}}=>[KNN 1 @embedding $query_vec]",
        "PARAMS", "2", "query_vec", query_vec,
        "DIALECT", "2",
    )

    if results[0] > 0:
        fields = results[2]
        field_dict = {fields[j]: fields[j+1] for j in range(0, len(fields), 2)}
        distance = float(field_dict.get("__embedding_score", "999"))
        if distance < threshold:  # Lower distance = more similar
            return {"hit": True, "response": field_dict.get("response", ""), "distance": distance}

    return {"hit": False}
```

**catatan**  
Filter `@user_id:{user_123}` TAG memastikan bahwa percakapan cache Pengguna A tidak bocor ke Pengguna B. Kueri hibrida (TAG \+ KNN) berjalan sebagai operasi atom tunggal — pra-pemfilteran oleh pengguna, lalu menemukan konteks percakapan terdekat.

## Strategi isolasi cache
<a name="semantic-caching-isolation-strategies"></a>


| Strategi | FILTER TAG | Terbaik untuk | 
| --- | --- | --- | 
| Per-user | @user\_id:{user\_123} | Asisten yang dipersonalisasi | 
| Per-session | @session\_id:{sess\_abc} | Short-lived obrolan | 
| Global (dibagikan) | Tidak ada filter (\*) | FAQ bot, pertanyaan umum | 
| Per-model | @model:{gpt-4} | Multi-model penyebaran | 
| Per-product | @product\_id:{prod\_456} | E-commerce asisten | 