Files

89 lines
5.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Roadmap
Not a generic TODO list — this captures the **intended architecture progression** and *why* each phase is sequenced that way.
## Phase 1 — Telegram AI Foundation ✅ (current)
TypeScript + grammY, Docker dev mode with hot reload, webhook + long-polling,
`/start` `/help`, normalized message contract, LLM via LiteLLM, conversation
persistence in Postgres, one controlled n8n path, tests + docs.
**Why this order**: prove the transport (Telegram webhook) and the AI loop end-to-end
before investing in durable context, RAG, or a second channel.
## Phase 2 — Durable Context + Business Tools
**Progress (2026-08-30):**
-**Product catalog awareness**`CatalogRetriever` (`src/ai/retrieval/catalog.ts`)
replaces `NoopRetriever`: SKU-token + name/category keyword lookup over the
generated `src/data/catalog.ts` (259 entries, built by `gen_catalog.py` from
`catalog_sku.csv`; no prices, no storage paths). Hits are injected into the
prompt as "Product facts" with product-page links
(`https://www.digikedai.com/products/<sku>/`); free items (SKU prefix FREE —
FREECXM04 = FREE + original paid SKU CXM04, the trial twin) are flagged and routed to
`/free/`. Keyword search chosen over pgvector
at this scale (eval criteria below).
-**Passive human-handoff** in `system.ts` — admin contact (Telegram
@MrFullStackDev only, no WhatsApp/phone) is offered only when the customer
asks for a human or the bot cannot solve the issue; repeat questions are
re-answered with one ask-line (deterministic `isRepeatQuery` on top of
memory last_queries); URLs must stand alone on their own line; reply
language mirrors the customer (language_code mapped to friendly names).
-**Purchase flow: multi-way state machine + inline buttons** (第13批, 2026-08-31)
— deterministic `pendingPurchase` state machine (mirrors the free-trial
`pendingTrials` pattern) replaces the single admin deep link. Purchase intent
is intercepted in `message:text` via `PURCHASE_INTENT_RE` (zh/en/ms, SKU-aware;
FREE-prefixed trial SKUs are never intercepted) → a two-row inline keyboard:
① 网店下单 (online store / marketplace — neutral words, preferred, row on top)
→ neutral guidance + 联系 admin / 返回 buttons; ② 找 admin 购买 → admin deep
link issued DIRECTLY (fallback, fast). 「返回」re-shows the menu; every
callback branch ends with `answerCallbackQuery()` (Telegram retry idempotency).
Deep-link prefill is a free-text sentence in the customer's language built by
`buildAdminPurchaseLink({sku?, paymentPreference?, username?, lang?})`
whatever was collected (SKU / payment preference / labelled username), nothing
forced; no SKU → generic product message. The URL is `encodeURIComponent`'d
exactly ONCE in code; the prompt carries two static pre-encoded samples
(with/without username) and the model only swaps alphanumeric SKU/username —
this killed the double-nesting bug (第1批 f27bbb4). **中性词纪律**: no
Shopee/Lazada/Add-On/TnG/bank-in anywhere in bot copy until the marketplace
is live (test-asserted). Full plan: `docs/PURCHASE_FLOW_REDESIGN.md`.
-**Free-trial flow button-ified** (第3批, 2026-08-31) — `startSku` /
`confirmReuse` replies now carry inline buttons (✅ 确认并开通 / ✏️ 提供新
username / ♻️ 加到现有账号) dispatched into the `pendingTrials` state machine;
the legacy text path (同意 / 新账号 xxx / 用户名:…) still works unchanged.
Remaining items:
- Enrich user profile & conversation memory (`src/ai/memory`).
- Explicit tool schemas (product lookup, order lookup, status, free-account) with validation before n8n execution.
- Admin/user authorization + rate limiting; allowlist enforced in production.
- Logging, correlation IDs, observability.
- Formalize Channel/Core contracts so Shopee/Lazada adapters drop in without touching the AI core.
**Why now**: only once Phase 1 shows what the customers actually ask.
## Phase 3 — RAG + Multi-Channel
- Enable `pgvector` in the existing `pgvector/pgvector:pg17` Postgres (already provisioned) when keyword lookup becomes insufficient.
- Ingestion pipeline for docs/FAQs/products/policies.
- Retrieval evaluation + source attribution/citation.
- Shopee adapter (merchant/chat API), then Lazada adapter.
- Channel-specific personas/prompts while keeping shared product/customer context.
- Consider a separate vector DB **only** if pgvector becomes a real bottleneck.
**Why pgvector before Qdrant**: vectors live alongside ordinary Postgres data;
exact + ANN search; keeps the architecture smaller until scale demands separation.
## Criteria for adding new infrastructure
Before introducing any new service, explain operational cost and confirm the existing
stack (Postgres, n8n, Traefik, LiteLLM) can't already meet the need. Non-goals to
protect: no Qdrant/vector DB without a concrete requirement, no multi-agent swarm,
no model fine-tuning, no Dify unless it earns its place.
## Risks / open items
- **LiteLLM shared key**: bot currently uses the mem0 LiteLLM master key. Phase 2 should mint a dedicated virtual key (rate-limit + revoke isolation). See `docs/DECISIONS.md`.
- **Webhook auth**: `TELEGRAM_WEBHOOK_SECRET` guards the URL path; keep it strong in production.
- **Free-account workflow**: the exact n8n workflow path/schema is still a placeholder — confirm with the actual workflow before wiring it to the LLM as a tool.