Plán: chatbot nad programem a obsahem webu
Plán: chatbot nad programem a obsahem webu
Stav: návrh k odsouhlasení · Založeno 1. 8. 2026
Cíl
Chatbot na brandysboleslav.cz, který s návštěvníkem diskutuje náš politický
program a informace z webu. Odpovídá výhradně z našeho publikovaného obsahu
a u každého tvrzení odkáže na stránku, ze které čerpá. Když odpověď v podkladech
není, řekne to a nabídne kontakt — nedomýšlí politické pozice.
Rozhodnutí (1. 8. 2026)
- Základ: fork konextu (v2.8.0) a jeho osekání. Získáme hotový hybridní retrieval, chat widget, admin, evidenci nákladů a Quality Loop.
- Korpus: dlouhodobý program + aktuální články + odborné podklady (doprava, strategie, MHD) + lidé a kontakty. Materiály se budou průběžně doplňovat → ingestace musí být konfigurační, ne hardcodovaná.
Architektura cílového stavu
brandys-pirati (Jekyll, GitHub Pages)
├─ obsah: _program/, _posts/, doprava/, _people/ …
├─ scripts/export-korpus.mjs ──► korpus.json
│ │
│ ▼ convex run knowledgePages:importBulk
└─ _includes/footer-md3.html ──► <script src="…/embed.js">
│
▼
brandys-chatbot (fork konextu)
├─ Next.js 16 · /widget (veřejné) + /admin (Kinde)
└─ Convex: knowledgePages + knowledgeChunks + embeddings
vector + fulltext + RRF + parent-child retrieval
→ OpenRouter (LLM)
Fáze 0 — Založení repa a osekání
Nový repozitář brandys-chatbot z konextu. Mazat, ne nabalovat.
Pryč:
| Oblast | Soubory |
|---|---|
| Produkty a feed | convex/products.ts, sync.ts, productClicks.ts, tabulky products, productEmbeddings, productStats |
| Měny a domény | convex/currency.ts (cz/sk/hu/hr/eu), cenová logika v chatFormatting.ts |
| Zákazníci | convex/customerAuth.ts (JWT z CubeCartu), customer* pole v conversations |
| E-mailový kanál | convex/email*.ts (~2 800 ř.), src/components/email/, /admin/emails |
| Re-ranking produktů | rerankProducts v chatSearch.ts (accessory trap) |
| R2 / PII export | corpus*.ts, r2Storage.ts — dokud nebude důvod |
Zůstává: chat.ts, chatSearch.ts (RRF), chatAI.ts, chatPrompts.ts,
embeddings.ts, knowledgePages.ts, responseCache.ts, rateLimit.ts,
apiUsage.ts, answerJudge.ts + Quality Loop, widget a public/embed.js.
Kontrola hotovosti fáze: npm run test:ci prochází, npx convex dev nasadí
schéma bez produktových tabulek.
Fáze 1 — Korpus a ingestace
Rozšíření schématu knowledgePages
Ke stávajícím polím (url, title, content, categoryMappings) přidat:
-
sourceType:programclanekpodkladosobakontakt -
publishedAt(timestamp) avalidity:aktualnihistoricky sourceFile— cesta v repu, aby šlo dohledat, odkud věta pochází
Exportní skript — HOTOVO (2. 8. 2026)
scripts/export-korpus.mjs, zdroje v scripts/korpus-zdroje.json, aby šlo
doplňovat bez zásahu do kódu. Čte markdown, ne HTML — je čistší než
scrapovaný web a nese frontmatter (datum, kategorii, tagy).
URL se ověřuje proti _site, neodvozuje se jen z názvu souboru: Jekyll
slug umí koncovou pomlčku uříznout (…-cez-.md → /…-cez/) a odkaz do prázdna
je u citací horší než chybějící dokument. Dokument bez dohledatelné URL skript
vynechá a nahlásí. Vyžaduje tedy sestavený web.
Výstup: korpus/davka-NN.json ve tvaru argumentu pro knowledgePages.importBulk,
plus souhrn.json se statistikou a seznamem problémů. Adresář je v .gitignore.
Stav korpusu: 118 dokumentů, 765 tis. znaků, 6 dávek
| Zdroj | Počet | Druh | Platnost |
|---|---|---|---|
_program/dlouhodoby/ |
13 | program | aktuální |
_posts/strategie/ |
7 | program | aktuální |
_posts/ (od 2025) |
10 | článek | podle data |
_posts/mistostarosti/ |
63 | článek | historický |
_posts/proposals/ |
18 | podklad | aktuální |
doprava-metodika.md |
1 | podklad | aktuální |
_people/ |
6 | osoba | aktuální |
_podklady/ |
0 | podklad | nepublikované |
Místostarosti (12/2022–7/2025) jsou dobové sloupky z funkce, ne programové
dokumenty — proto natvrdo validity: historicky. Bot je bude citovat jako
minulost („v Místostarostech z 4. 6. 2023 jsme psali…”), ne jako dnešní pozici.
Články mají hranici odData: 2025-01-01, což vynechává 70 starších
(kampaně 2018 a 2022). Odpovídá to výběru korpusu ze 1. 8. — archiv nebyl
zvolen. Zapnout jde posunutím nebo smazáním jednoho pole v konfiguraci.
Import
brandys-chatbot/scripts/import-korpus.mjs projde dávky a pošle je do
knowledgePages.importBulk (idempotentní přes URL — opakovaný běh aktualizuje,
nezdvojuje). S --embeddings rovnou spustí regeneraci.
# 1. v brandys-pirati (vyžaduje sestavený _site)
node scripts/export-korpus.mjs
# 2. v brandys-chatbot (vyžaduje běžící convex dev / nastavený deployment)
node scripts/import-korpus.mjs --embeddings
Vyloučit explicitně:
_people/_priklad.md,_posts/_priklad.md— šablony s výplňovým textem_archive/,_site/,export_wayback/
Import: npx convex run knowledgePages:importBulk (mutace v konextu už existuje,
je idempotentní přes url), pak embeddings:regenerateAllEmbeddings.
Nepublikované podklady
Materiály, které nemají být na webu jako stránka, ale bot z nich smí čerpat a citovat je. Zadání ze 1. 8. 2026: nejde o utajení obsahu, jen o to, že se nepublikují.
Umístění: adresář _podklady/ v tomto repu. Jekyll adresáře začínající
podtržítkem do _site nekopíruje (ověřeno — v _site žádný takový není), takže
se na web nedostanou; exportní skript je bere jako běžný zdroj
(sourceType: podklad, publikovano: false). Do exclude v _config.yml je
přidat jako druhou pojistku.
Co tam smí: protože bot obsah reprodukuje návštěvníkům, je fakticky veřejný,
jen bez URL. Navíc repozitář tangero/brandys-pirati je veřejný, takže soubory
jsou čitelné i přímo na GitHubu. Nepatří sem interní strategie kampaně, osobní
údaje ani nic, co by nemělo zaznít.
Citace bez cíle — u nepublikovaného podkladu odkaz nikam nevede. Dvě cesty, rozhodnutí je na zadavateli:
- bot cituje jménem dokumentu bez odkazu („podle naší analýzy dopravy z 3/2026”)
- dokument se v okamžiku, kdy z něj bot veřejně cituje, publikuje — doporučeno, publikovaná verze je lepší než parafráze bez zdroje
Spouštět ručně; automatizaci přes GitHub Action až po ověření. Pozor:
npm run build je v tomto repu mrtvý a nebezpečný (přepsal by _config.yml),
ingestace se ho nesmí dotknout.
Fáze 2 — Prompt, citace a guardrails
Tři věci, které konext nemá a bez kterých bot nemůže ven:
- Citace.
chatPrompts.ts:252dnes URL odkazy zakazuje (e-shop je nahrazuje#IDproduktu). Přepsat knowledge sekci promptu tak, aby každá stránka šla do kontextu stitle+url, a vynutit odkaz u každého věcného tvrzení. - Datová platnost. Do promptu předat
publishedAtavaliditys pravidlem, že historické materiály se citují jako historie („v roce 2022 jsme navrhovali”), nikdy jako současná pozice. - Tvrdé „nevím”. Vymyšlený politický závazek je horší než chybějící odpověď.
Překlopit
escalationDecision.tsna „na tohle nemáme veřejnou pozici, napište nám na …”. Doplnit pravidla pro provokace, dotazy na konkurenci a osobní útoky.
Dále: nový systémový prompt (tón — věcný, nekampaňový), viditelné označení „odpovídá AI, může se mýlit” ve widgetu, GDPR režim logování konverzací.
Fáze 3 — Evaluace
Sada reálných otázek voličů v docs/chatbot-otazky.md (obchvat, kulturní dům,
parkování, školy, MHD, „proč jste skončili na radnici”, „co jste reálně dokázali”).
Ke každé očekávaný zdroj. Projet přes Quality Loop (answerJudge, /admin/labeling),
měřit podíl odpovědí bez opory ve zdroji — to je jediné číslo, které rozhoduje
o vypuštění ven.
Fáze 4 — Nasazení
- Convex + Vercel, subdoména (např.
chat.brandysboleslav.cz) <script>do_includes/footer-md3.html(vedle Clicky analytics)- Kinde pro
/admin, verze v UI a health endpointu podle zvyklosti
Fáze 5 — Hlasové rozhraní (až po textu)
OpenAI vydala 7. 5. 2026 GPT-Realtime-2 (Realtime API přes WebSocket, WebRTC
i SIP, 128K kontext) a spolu s ním GPT-Realtime-Whisper pro streamovaný přepis.
Nepoužívat speech-to-speech. Model by mluvil přímo z audia a retrieval by si tahal přes function calling — tím obejde cache, snapshoty Quality Loopu i citace. Právě to je u politického bota jádro obhajitelnosti a nahrávka je zdaleka nejsdílitelnější artefakt.
Místo toho hlas jako vrstva nad textovou pipeline:
mikrofon → GPT-Realtime-Whisper (přepis)
→ stávající retrieval + citace + Quality Loop
→ odpověď s odkazy na obrazovce + TTS
Latence horší, ale u diskuse o obchvatu nerozhoduje. Zachová logování, měření halucinací i viditelné zdroje — a audio-in/audio-out je řádově levnější než speech-to-speech.
K ověření před nasazením: GDPR režim pro hlas návštěvníka (citlivější než textový log, zvlášť v předvolebním období) a výslovnost místních jmen — Houštka, Zápy, Vrábí, Brandýs nad Labem-Stará Boleslav.
Rizika
- Halucinovaný závazek — hlavní riziko celého projektu. Mitigace: citace, tvrdé „nevím”, evaluační sada, konzervativní temperature.
- Zastaralý obsah jako aktuální pozice — 70 z 80 článků je starších než 2025.
- Volební období — dnes 1. 8. 2026, komunální volby na podzim. Zvážit chování bota v době volebního moratoria a připravit vypínač.
- Zneužití k útoku — screenshot nešťastné odpovědi. Řešení: logovat vše, mít možnost bota okamžitě vypnout.
Otevřené otázky
- Kde je DNS pro
brandysboleslav.cz(subdoména pro Vercel)? - Vercel Hobby vs. Pro — politický projekt strany, komerční licence?
- Kdo bude číst logy konverzací a jak často?