MemoDocumentation
EN

Chat System

The chat interface is the primary interaction surface of Memo. It supports real-time streaming, rich content rendering, and deep integration with the local backend.

Streaming Architecture

Messages are delivered token-by-token over Server-Sent Events (SSE). The Go backend streams tokens as they are generated by the inference engine:

// Backend SSE handler pattern
w.Header().Set("Content-Type", "text/event-stream")
w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Connection", "keep-alive")

for token := range llm.Stream(ctx, prompt) {
    fmt.Fprintf(w, "data: %s\n\n", token)
    flusher.Flush()
}

The Flutter frontend renders each token immediately via Riverpod state updates, creating the appearance of the model "typing" in real time.

Response Rendering

All model responses are parsed as GitHub-Flavored Markdown and rendered with full support for:

Format Support
Headings H1–H6 with anchor IDs
Code Blocks Syntax highlighting via highlight.js (Go, Python, JS, Bash, YAML, JSON, Dart)
Inline Code Monospace with bronze accent
Tables Responsive, striped hover rows
Lists Ordered and unordered, nested
Blockquotes Styled callouts ([!NOTE], [!WARNING], [!TIP], [!DANGER])
Links Auto-linked URLs, internal doc cross-references
Images Rendered inline from markdown image syntax

File & Image Drop

Drag and drop files or images directly into the chat input area:

  • Images: Encoded as Base64 locally. Sent to multimodal GGUF models for vision analysis. Never uploaded to external servers.
  • Documents (PDF, TXT, MD): Ingested into RAG memory. The file content is chunked, embedded, and stored for future recall.
  • Code Files: Displayed with syntax highlighting in the chat. Optionally indexed for semantic search.

Slash-Command Palette

Type / in the chat input to reveal the command palette:

Command Action
/agent Activate Agent Mode for tool-calling workflows
/orchestra Start Orchestra Mode with expert roles
/search Search RAG memory with semantic query
/model Switch active model
/incognito Toggle incognito mode
/clear Clear current conversation
/export Export conversation to Markdown

On-Device Voice Input

Speech-to-text runs entirely on-device via whisper.cpp (bundled with the application):

  • No network required — transcription happens locally
  • TR/EN auto-detection — automatically switches between Turkish and English models
  • Push-to-talk — hold the mic button, release to send
# whisper.cpp runs as a subprocess managed by the Go backend
whisper-cli -m models/ggml-base.bin -f audio.wav -l auto

Web Search Integration

The globe icon in the chat top bar toggles web search. When it's on, the model gets a web_search tool (DuckDuckGo, no API key needed) via native function-calling, in the same request that produces its reply — it decides per message whether the question actually needs a live search, and picks its own query, rather than every message triggering a search regardless of content. See Agent Mode for the full mechanism, which this toggle shares with Agent Mode's own toolset (just scoped down to this one tool). Turned off entirely under Minimal Mode.

Incognito Mode

Toggle incognito mode to create ephemeral sessions. In this mode:

  • No messages are written to disk
  • No vector embeddings are created
  • No memory recall is performed
  • Session ends when you close the tab or toggle off


Use incognito mode for sensitive discussions, one-off queries, or testing model behavior without polluting your memory store.

Performance

  • First-token latency: Usually under 100ms for local models
  • Streaming buffer: 1-token granularity — no batching delay
  • Markdown parsing: Client-side via marked with deferred syntax highlighting
  • Memory: Chat history held in-memory during session; written to disk on close (unless incognito)