Scenario Experience


Feishu
Choose your preferred way to join


Every conversation is an island - this is the pain point of traditional AI assistants. User-stated preferences, corrected mistakes, and established context are all lost in the next conversation. AskTable's newly introduced permanent memory system is breaking this困局.
┌─────────────────────────────────────────┐
│ Conversation 1 │
│ User: What's East China sales? │
│ AI: 12 million │
│ User: For what time period? From now on │
│ when answering sales metrics, │
│ include specific time │
│ AI: Got it. Q1 2026 East China sales │
│ is 12 million │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ Conversation 2 (any time later) │
│ User: How's East China profit? │
│ AI: Q1 2026 net profit 3.5 million, │
│ YoY +18%, QoQ +5% │ ← Automatically with time
└─────────────────────────────────────────┘
Root cause: In traditional architecture, conversation history is only valid within a single session.
This "amnesia" leads to:
AskTable chose mem0 OSS as the memory framework, core reasons:
| Consideration | mem0 Advantage |
|---|---|
| Ready to use | Built-in deduplication, conflict resolution, expiration mechanism |
| Simple API | Four core methods: add / search / get_all / delete |
| Replaceability | Abstracted through Protocol, can switch to custom solution later |
| Async support | Native AsyncMemory, perfectly fits asyncio architecture |
┌─────────────────────────────────────────────────────────────┐
│ AskTable Vector Storage Architecture │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Qdrant │ │ Qdrant │ │
│ │ (existing) │ │ (memory- │ │
│ │ metadata │ │ dedicated) │ │
│ │ retrieval │ │ cross-session│ │
│ │ │ │ memory │ │
│ └──────────────┘ └──────────────┘ │
│ │
│ Shared infrastructure, reduced operations cost │
│ │
└─────────────────────────────────────────────────────────────┘
Reuses existing Qdrant instance, no new infrastructure dependencies introduced.
┌─────────────────────────────────────────────────────────────┐
│ Memory System Workflow │
├─────────────────────────────────────────────────────────────┤
│ │
│ Conversation starts │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ Memory Search │ ← Search related memories with query │
│ └────────┬────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ Format and inject│ ← Splice into System Prompt │
│ │ memory_context │ │
│ └────────┬────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ Agent generates │ ← Carry memory context │
│ │ response │ │
│ └────────┬────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ Memory Write │ ← Async write after conversation ends │
│ └─────────────────┘ (fire-and-forget) │
│ │
└─────────────────────────────────────────────────────────────┘
Read (Search) at request start:
Write (Add) after response completes:
┌─────────────────────────────────────────────────────────────┐
│ Memory Isolation Model │
├─────────────────────────────────────────────────────────────┤
│ │
│ DataAgent-A │
│ ┌─────────────────────────────────┐ │
│ │ Memory space: agent_id = "agent-a"│ │
│ │ - User preferences │ │
│ │ - Common reports │ │
│ │ - Analysis habits │ │
│ └─────────────────────────────────┘ │
│ │
│ DataAgent-B (independent memory) │
│ ┌─────────────────────────────────┐ │
│ │ Memory space: agent_id = "agent-b"│ │
│ │ - Different user preferences │ │
│ │ - Different business scenarios │ │
│ └─────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
Design principle: All users under the same Data Agent share memory (team knowledge base mode).
class MemoryService(Protocol):
"""Memory service abstraction, supports later replacement"""
async def add(
self,
messages: list[dict],
agent_id: str,
metadata: dict | None = None
) -> list[str]: ...
async def search(
self,
query: str,
agent_id: str,
top_k: int = 5
) -> list[MemoryItem]: ...
async def get_all(
self,
agent_id: str
) -> list[MemoryItem]: ...
async def delete(
self,
memory_id: str
) -> None: ...
Value: Through Protocol abstraction, ensuring mem0 is just one implementation, can smoothly switch to custom solution later.
# Extract key info from memory, format as natural language
MEMORY_CONTEXT_TEMPLATE = """
## Historical Memory
{relevance_memories}
Here are historical information relevant to you. Please answer user questions combined with this context.
"""
Example output:
## Historical Memory
- When user asks about sales, profit margin and other metrics, should include specific time period (2026-04-01)
- User mainly focuses on East China region data (2026-03-15)
- Prefers showing YoY and QoQ growth rates in charts (2026-03-20)
Here are historical information relevant to you. Please answer user questions combined with this context.
async def run_conversation_task(ctx: Context, ...):
# ... Execute conversation ...
# After releasing lock, async write memory
await release_lock()
await stream_end()
# Fire-and-forget, doesn't block user receiving response
asyncio.create_task(
memory_service.add(
messages=full_conversation,
agent_id=data_agent_id
)
)
Before (no memory):
User: What's East China sales?
AI: 12 million
User: For what time period?
AI: This is Q1 data
User (another day): How's East China profit?
AI: Q1 2026 net profit 3.5 million
[No time dimension, don't know which time period]
After (has memory):
User: What's East China sales?
AI: 12 million
User: For what time period? From now on when answering sales metrics, should include specific time
AI: Got it. Q1 2026 East China sales is 12 million
User (another day): How's East China profit?
AI: Q1 2026 net profit 3.5 million, YoY +18%, QoQ +5%
← Automatically with time dimension, no need to repeat
| Scenario | No Memory | Has Memory |
|---|---|---|
| Data query | Ask region, time range every time | Automatically use preference settings |
| Report generation | Specify format every time | Auto-generate per habit |
| Anomaly analysis | Explain focus metrics every time | Automatically track historical concerns |
| Trend interpretation | Explain business context every time | Automatically associate historical insights |
The system added a "Memories" Tab to the Data Agent configuration page:
Challenge: mem0 needs 1-2 LLM calls per add() for fact extraction.
Response:
memory_enabled switch)Challenge: mem0's fact extraction prompt mainly targets English.
Response:
Challenge: When memory errors occur, need to trace mem0 internal链路.
Response:
| Solution | Memory Granularity | Implementation Difficulty | Maintenance Cost | Applicable Scenario |
|---|---|---|---|---|
| Session Storage | Session level | Low | Low | Temporary storage |
| User KV Store | User level | Medium | Medium | Simple preferences |
| mem0 | Agent level | Medium | Medium | Complex context |
| Custom vector DB | Flexible | High | High | Deep customization |
AskTable's choice: mem0 is the "fast validation" path, Protocol abstraction leaves room for "long-term evolution".
If mem0 performs poorly in Chinese data analysis scenarios, can switch to custom solution:
Existing infrastructure:
├── Qdrant (vector storage)
├── BAAI/bge-small-zh-v1.5 (Embedding)
└── Langfuse (observability)
Custom development needs to solve:
├── Fact extraction Prompt
├── Deduplication/conflict strategy
└── Memory decay mechanism
AskTable permanent memory system's introduction marks AI data analysis assistant's evolution from "reactive tool" to "intelligent partner":
Core value:
Technical highlights:
Product significance: Memory system lets AI truly "recognize" users, not just answer questions. This is the key step from "tool" to "assistant".
No coding required. Ask questions in natural language and AI generates SQL queries and visualizations automatically.
Start your free trial now and experience AI-powered data analysis with AskTable.