-
Notifications
You must be signed in to change notification settings - Fork 99
LCORE-1675: Documentation for conversation compaction #2434
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -35,7 +35,7 @@ To keep requests on-topic and protect sensitive data, LCore applies **safety shi | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - **Multi-Provider Support**: Works with multiple LLM providers (Ollama, OpenAI, Watsonx, etc.) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - **Enterprise Security**: Authentication, authorization (RBAC), and secure credential management | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - **Resource Management**: Token-based quota limits and usage tracking | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - **Conversation Management**: Multi-turn conversations with history and caching | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - **Conversation Management**: Multi-turn conversations with history, caching, and automatic compaction | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - **RAG Integration**: Retrieval-Augmented Generation for context-aware responses | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - **Tool Orchestration**: Model Context Protocol (MCP) server integration | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - **Observability**: Prometheus metrics, structured logging, and health checks | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -370,6 +370,83 @@ External A2A requests go through LCore's standard authentication system (K8s, RH | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ### 2.11 Conversation Compaction (`utils/compaction.py`, `utils/conversation_compaction.py`) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| **Purpose:** Automatically summarize older conversation turns when the conversation history approaches the LLM's context window limit, preventing HTTP 413 failures and enabling arbitrarily long conversations. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| **Design Philosophy (Option A):** Once compaction triggers, LCore takes ownership of the context sent to the LLM. The `conversation` parameter is dropped from the OGX call (`omit_conversation=True`), and LCore constructs the input explicitly from summaries + recent turns + new query. The full original history remains in OGX for auditing. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| **Architecture:** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| The compaction system is split into two layers: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 1. **Pure Logic Layer** (`utils/compaction.py`) — Side-effect-free functions: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - `partition_conversation()` — Splits conversation items into old and recent chunks using a *degrading guard*: starts with the configured `buffer_turns` and shrinks one pair at a time until the recent chunk fits the token budget | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - `summarize_chunk()` — Single LLM call to produce a `ConversationSummary` from older turns | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - `recursively_resummarize()` — Folds multiple accumulated summaries into one when they approach the context limit | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 2. **Runtime Integration Layer** (`utils/conversation_compaction.py`) — Manages side effects: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - Per-conversation locking (serializes concurrent requests on the same conversation) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - Compaction state loading (cache-preferred with marker fallback) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - Marker persistence (`[lightspeed:compaction-summary]` sentinel in conversation items) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - `CompactionStartedEvent` emission for streaming progress indicators | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - `apply_compaction()` (async generator) — Main entry point used by all endpoints | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - `store_compacted_turn()` — Appends user query + LLM output when in compacted mode | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| **Data Flow:** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| User Query → Estimate Tokens → Exceeds Threshold? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| │ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| No │ Yes | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ↓ │ ↓ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Pass-through Acquire Lock | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ↓ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Fetch Conversation Items | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ↓ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Load Compaction State | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (cache → marker fallback) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ↓ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Partition (old | recent) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ↓ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Summarize Old Chunk (LLM call) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ↓ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Write Marker + Cache Summary | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ↓ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Recursive Fold (if needed) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ↓ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Build Explicit Input: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [summaries + recent + query] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ↓ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Set omit_conversation=True | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ↓ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Release Lock → Continue to LLM | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+398
to
+424
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win Add a language to the fenced diagram block.
Based on static analysis: Proposed fix-```
+```text📝 Committable suggestion
Suggested change
🧰 Tools🪛 markdownlint-cli2 (0.23.2)[warning] 398-398: Fenced code blocks should have a language specified (MD040, fenced-code-language) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| **Endpoint Integration:** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | Endpoint | Mode | Cache | `context_status` | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| |---|---|---|---| | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | `/v1/query` | Blocking (`apply_compaction_blocking()`) | Yes | Yes (`"full"` / `"summarized"`) | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | `/v1/streaming_query` | Streaming (`apply_compaction()` generator) | Yes | Yes (in `end` event) | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | `/v1/responses` | Blocking | Yes | No (OpenAI-compatible, silent) | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | `/a2a` | Blocking, marker-only (no cache) | No | No (A2A protocol scope) | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| **Configuration:** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Compaction is controlled by `CompactionConfiguration` in `lightspeed-stack.yaml`: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - `enabled` (default: `false`) — Master switch | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - `threshold_ratio` (default: `0.7`) — Fraction of context window that triggers compaction | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - `token_floor` (default: `4096`) — Minimum token count before compaction can fire | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - `buffer_turns` (default: `4`) — Recent turns kept verbatim | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - `buffer_max_ratio` (default: `0.3`) — Max fraction of window for the buffer | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Models must have context windows registered via `inference.context_windows` (a map of model ID to token count). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| **Concurrency:** A per-conversation lock dictionary serializes concurrent compaction requests on the same conversation. Lock entries are reference-counted and cleaned up when the last waiter exits. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ## 3. Request Processing Pipeline | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| This section illustrates how requests flow through LCore from initial receipt to final response. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -400,11 +477,12 @@ Here's how a real query flows through the system: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 5. **Model Selection** - Use configured default model (e.g., `meta-llama/Llama-3.1-8B-Instruct`) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 6. **Context Building** - Retrieve conversation history, query RAG vector stores for relevant docs, determine available MCP tools | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 7. **Shield moderation** - LCore-owned direct-run moderation (and agent capabilities where applicable) using shields configured in LCORE config | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 8. **Llama Stack / agent call** - Send request with system prompt, RAG context, and MCP tools | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 9. **LLM Processing** - Stack / agent generates response, may invoke MCP tools, returns token counts | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 10. **Post-Processing** - Generate conversation summary if new | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 11. **Store Results** - Save to Cache DB, User DB, consume quota, update metrics | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 12. **Return Response** - Complete LLM response with referenced documents, token usage, and remaining quota | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 8. **Conversation compaction** - If enabled and estimated tokens exceed the threshold, summarize older turns and rebuild the context (see [Section 2.11](#211-conversation-compaction-utilscompactionpy-utilsconversation_compactionpy)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 9. **OGX / agent call** - Send request with system prompt, RAG context, and MCP tools | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 10. **LLM Processing** - Stack / agent generates response, may invoke MCP tools, returns token counts | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 11. **Post-Processing** - Generate conversation summary if new | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 12. **Store Results** - Save to Cache DB, User DB, consume quota, update metrics | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 13. **Return Response** - Complete LLM response with referenced documents, token usage, and remaining quota | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| **Key Takeaways:** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - RAG enhances responses with relevant documentation | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -145,6 +145,7 @@ The optional `solr` field configures Solr inline RAG behavior: | |
| | `tool_results` | array[object] | `[]` | Tool call results | | ||
| | `rag_chunks` | array[object] | `[]` | *(Deprecated)* RAG chunks used | | ||
| | `truncated` | boolean | `false` | *(Deprecated)* Always `false` | | ||
| | `context_status` | string | `"full"` | Whether the conversation context is `"full"` (complete history) or `"summarized"` (older turns were summarized via conversation compaction) | | ||
|
|
||
| **`referenced_documents` items:** | ||
|
|
||
|
|
@@ -242,7 +243,7 @@ Emitted when the full response is assembled. | |
|
|
||
| #### 7. `end` | ||
|
|
||
| Emitted last on success. Contains metadata. | ||
| Emitted last on success. Contains metadata including `context_status` (`"full"` or `"summarized"`). | ||
|
|
||
| ```json | ||
| { | ||
|
|
@@ -251,7 +252,8 @@ Emitted last on success. Contains metadata. | |
| "referenced_documents": [], | ||
| "truncated": null, | ||
| "input_tokens": 11, | ||
| "output_tokens": 19 | ||
| "output_tokens": 19, | ||
| "context_status": "full" | ||
| }, | ||
| "available_quotas": {"UserQuotaLimiter": 998911} | ||
| } | ||
|
|
@@ -327,9 +329,9 @@ Both endpoints share the same pre-processing pipeline: | |
| 11. Prepare Responses API parameters (model, system prompt, tools, MCP headers) | ||
| 12. Extract image attachments separately for multimodal input construction | ||
|
|
||
| **`/v1/query` then:** applies conversation compaction (blocking), calls the LLM, generates topic summary, consumes tokens, stores results, returns JSON. | ||
| **`/v1/query` then:** applies conversation compaction (blocking), calls the LLM, generates topic summary, consumes tokens, stores results, returns JSON. When compaction is applied, the response includes `context_status: "summarized"`; otherwise `context_status: "full"`. | ||
|
|
||
| **`/v1/streaming_query` then:** generates a `request_id`, starts the SSE stream, emits events as the LLM generates tokens, performs post-stream cleanup (topic summary, token consumption, persistence). | ||
| **`/v1/streaming_query` then:** generates a `request_id`, starts the SSE stream, applies compaction if needed (emitting a `compaction` SSE event), emits events as the LLM generates tokens, performs post-stream cleanup (topic summary, token consumption, persistence). The `end` event includes `context_status` indicating whether compaction was applied. | ||
|
Comment on lines
+332
to
+334
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win Clarify that The runtime sets Based on learnings: 🤖 Prompt for AI AgentsSource: Learnings |
||
|
|
||
| --- | ||
|
|
||
|
|
@@ -409,7 +411,8 @@ curl -X POST http://localhost:8090/v1/query \ | |
| "tool_calls": [], | ||
| "tool_results": [], | ||
| "rag_chunks": [], | ||
| "truncated": false | ||
| "truncated": false, | ||
| "context_status": "full" | ||
| } | ||
| ``` | ||
|
|
||
|
|
@@ -500,7 +503,7 @@ data: {"event": "token", "data": {"id": 2, "token": " an"}} | |
|
|
||
| data: {"event": "turn_complete", "data": {"id": 50, "token": "Kubernetes is an open-source..."}} | ||
|
|
||
| data: {"event": "end", "data": {"referenced_documents": [], "truncated": null, "input_tokens": 11, "output_tokens": 50}, "available_quotas": {"UserQuotaLimiter": 998950}} | ||
| data: {"event": "end", "data": {"referenced_documents": [], "truncated": null, "input_tokens": 11, "output_tokens": 50, "context_status": "full"}, "available_quotas": {"UserQuotaLimiter": 998950}} | ||
| ``` | ||
|
|
||
| ### Streaming Query Interrupt | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Correct the processing order in the data-flow diagram.
apply_compactionacquires the per-conversation lock and loads conversation items before token estimation when compaction is enabled. The diagram estimates first and locks only on theYesbranch. It also omits the enabled and registered-context-window checks. Update the diagram to matchsrc/utils/conversation_compaction.py:493-617.🤖 Prompt for AI Agents