Developer notes
Architecture
Section titled “Architecture”question ─► limits, injection check, order intent ─► embedding of the question (AI service) ─► similarity search in PHP over ?:kv_aisa_sketches / ?:kv_aisa_chunks ─► live product data (fn_get_products + fn_gather_additional_products_data) ─► prompt: rules + store instructions + numbered sources + last 6 messages ─► chat completion (AI service) ─► checks: [[NO_ANSWER]] / [[OFF_TOPIC]] markers, product tags, price check ─► answer + product cards, stored conversation, knowledge gap- Embeddings are unit-normalised and stored as base64 float32 (
?:kv_aisa_chunks.vec), so cosine similarity is a dot product. - A 64-dimension seeded random projection of every vector is stored in the narrow table
?:kv_aisa_sketches. Up to 4,000 chunks in scope every vector is compared exactly; above that, the sketches are scanned in keyset pages of 5,000 rows and the best max(300, chunks / 120) are compared exactly. - Product chunks contain name, categories, vendor, code, features, variation features, options, descriptions and (optional) review texts, never price or stock.
- Chunks are about 900 characters along paragraph and sentence boundaries with a 120-character overlap; every chunk starts with its source line (for example
Product: Name).
Limits
Section titled “Limits”Measured with PHP 8.3, MariaDB 11.4, 768-dimension vectors, 10 queries each (recall@6 = share of the top 6 of a full exact scan that the search returned):
| Chunks in scope | Mode | Average search time | Memory | Recall@6 |
|---|---|---|---|---|
| 3,900 | exact | 0.19 s | 51 MB | 100% |
| 20,400 | pre-filter | 0.17 s | 6 MB | 100% |
| 50,400 | pre-filter | 0.44 s | 6 MB | 100% |
| 100,400 | pre-filter | 0.97 s | 11 MB | 100% |
The search time grows linearly with the number of chunks. Embedding and chat calls of the AI service add their own latency (with a local GPU model in our test: 0.2–3 s per answer).
Tables
Section titled “Tables”| Table | Contents |
|---|---|
kv_aisa_config |
Connection settings, encrypted API keys (fn_encrypt_text), cron key, run marks |
kv_aisa_docs |
One row per source (type + id), text hash, model, chunk count, status |
kv_aisa_chunks |
Chunk text and vector |
kv_aisa_sketches |
Pre-filter vectors (narrow table) |
kv_aisa_queue |
Sources waiting for the sync |
kv_aisa_files |
Uploaded documents (extracted text only) |
kv_aisa_faq |
FAQ entries |
kv_aisa_conversations, kv_aisa_messages |
History, ratings, flags, tokens, cost |
kv_aisa_gaps |
Unanswered questions grouped by normalised text |
kv_aisa_usage |
Daily requests, tokens and cost per kind (chat, embed) |
kv_aisa_rate |
Rate-limit windows (salted IP hashes) |
kv_aisa_codes |
One-time order codes (HMAC, 10 minutes) |
kv_aisa_vendors |
Per-vendor switch (Multi-Vendor) |
dispatch_before_display (widget configuration), update_product_post, delete_product_post, update_page_post, delete_page (sync queue), delete_company (vendor data). The arguments are identical in 4.17.2 and 4.21.2. Storefront template hook: index:footer (post). E-mail template: kv_ai_shopping_assistant_code (Twig, valid in Twig 2 and 3).
Controllers
Section titled “Controllers”- Storefront
kv_ai_shopping_assistant.chat|history|rate|orders|order_code|order_verify(POST, JSON) and.cron(GET with key). - Admin
kv_ai_shopping_assistant.manage|connection|knowledge|faq_update|conversations|conversation|gaps|vendors, AJAXsync_step,test_connection,preview; consolephp admin.php --dispatch=kv_ai_shopping_assistant.cron [--reconcile=1]. - Vendor panel:
vendor,vendor_toggle,faq_update,faq_delete,file_upload,file_delete(ownership checked).
Development seam
Section titled “Development seam”define('KV_AISA_MAIL_CAPTURE', '/path/mail.log'); in config.local.php of a development store renders the order code e-mail with the real template and appends it to that file instead of sending it.
Full page cache (4.21)
Section titled “Full page cache (4.21)”Designed for it, not yet tested with the full page cache switched on. The index:footer output depends only on the settings and the page (vendor of the product shown), never on the visitor. The conversation token lives in localStorage; every request is an AJAX POST to the add-on’s controller.
License
Section titled “License”Tygh\Addons\KvAiShoppingAssistant\License\Client (domain-bound). Gated: the storefront widget and all its requests, the HTTP cron and the knowledge base sync. Kept: admin pages and all data.
Roadmap
Section titled “Roadmap”Ideas for later versions, not part of 1.0: an assistant for staff inside the admin panel (orders, products, reports), a knowledge base built from more than one storefront language, and voice input in the widget.
File map
Section titled “File map”app/addons/kv_ai_shopping_assistant/ addon.xml init.php func.php controllers/frontend/kv_ai_shopping_assistant.php storefront JSON + HTTP cron controllers/backend/kv_ai_shopping_assistant.php admin and vendor pages, console cron controllers/backend/kv_ai_shopping_assistant_license.php schemas/menu/{menu,menu_vendor,actions}.post.php schemas/permissions/{admin,vendor_multivendor}.post.php Tygh/Addons/KvAiShoppingAssistant/ Ai.php AiException.php OpenAI-compatible client (OpenAI, Azure, others) Assistant.php answer pipeline Retriever.php Vector.php similarity search Indexer.php Sources.php Text.php Pdf.php Files.php Faq.php Catalog.php live product data Orders.php order status lookup Guard.php Usage.php Gaps.php Stats.php Vendors.php Housekeeping.php Storefront.php Config.php Db.php License/ Upgrade/design/backend/templates/addons/kv_ai_shopping_assistant/ admin pages, license cardvar/themes_repository/responsive/templates/addons/kv_ai_shopping_assistant/hooks/index/footer.post.tpljs/addons/kv_ai_shopping_assistant/{func.js,admin.js}