Skip to content

Ask the AI with @ai in a channel - #3

Merged
raf-li merged 5 commits into
mainfrom
feature/ai-channel-chat
Oct 5, 2026
Merged

raf-li merged 5 commits into
mainfrom
feature/ai-channel-chat

Conversation

@raf-li

@raf-li raf-li commented Oct 4, 2026

Copy link
Copy Markdown
Member

Builds on #2 (the AI module). Merge #2 first; this PR then only adds its own commit. Merging this one alone also brings in #2.

What

Anyone can type in a channel:

@ai apa itu fotosintesis?

and the bot answers in that channel (not by PM), so everyone there hears it:

[AI] untuk Siti: Fotosintesis adalah ...
AI bisa salah. Periksa kembali info penting.
  • Short plain-text answers in the language of the question; Markdown symbols and bullets are stripped because screen readers read them aloud.
  • As an admin the bot can post to any channel without joining it (checked in the TeamTalk server source), so there are no join/leave sounds.
  • Follow-ups work: the channel's last AI_CHAT_HISTORY (3) questions and answers from the last 10 minutes go along. Nicknames are never sent to the AI.
  • @ai must be followed by a space, : or , (@aisyah halo is ignored). Private messages are not answered.
  • Per-person cooldown (AI_CHAT_COOLDOWN_SEC, 20 s) and a server-wide daily limit (AI_CHAT_DAILY_LIMIT, 200), told privately.
  • Answers containing a clear badword are replaced by a refusal; ambiguous ones ("Anjing adalah hewan yang setia") are fine. Failures post a short apology.
  • The question is still an ordinary channel message: badword filter and spam detection apply.
  • Off by default: /abt aichat on, refused until the Cloudflare credentials from AI context check for ambiguous badwords #2 are in config.json. /help ai explains it to users. Disclaimer text, prefix, model and limits are configurable (docs/ai.md).
  • Known limit: in classroom channels the server may refuse the bot's answer unless it is allowed to write there.

Tested

  • Fake Workers AI server: system prompt, history order, max_tokens/temperature, answer cleaning, empty answers.
  • Bot with the real TeamTalk DLL: off → ignored; channel interception switched on even without CHANNEL badword/spam types; answer posted to the asker's channel with name and disclaimer, not as PM; follow-up history per channel; cooldown and daily limit; empty question hint; @aisyah; badword in answer replaced; ambiguous word kept; failure apology; PM and the bot's own messages ignored; busy queue; refused without credentials; help texts.
  • All earlier suites pass. Not yet run against the real Workers AI.

🤖 Generated with Claude Code

raf-li and others added 3 commits October 5, 2026 00:41
"anjing tetanggaku berisik" is about a dog, "anjing lah" is a curse; a word
list cannot tell them apart.

- ai_review.py: Cloudflare Workers AI client on a background thread; results
  are handled on the main thread (the only one allowed to use the SDK)
- When every badword in a message is in AI_AMBIGUOUS_WORDS, the bot asks the
  AI first: insult -> counted, ok -> not counted, no answer -> not counted
  (agreed policy: better to miss a curse than warn a student about their dog)
- Clear badwords, or a mix with one, are still counted immediately
- Off by default; /abt ai switches it and refuses without credentials;
  /bwt shows the AI's verdict; tools/ai_eval.py scores a model on 32
  labelled sentences; setup in docs/ai.md
- Only the flagged message text is sent, never names or IPs

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A lone "anjing" right after "aku punya binatang baru waaa" names the new
pet, but on its own the AI reads it as a curse.

- Recent messages are kept in memory (only while the AI check is on): per
  channel for everyone in it, per sender for private messages (the SDK does
  not say who a PM was for). Commands and answers to the bot's prompts,
  such as passwords, are never kept; old entries are dropped
- On an ambiguous hit the bot waits 8 s, then sends up to
  AI_CONTEXT_MESSAGES (default 4) earlier messages from the last 2 minutes
  and up to 2 follow-ups, labelled only [same person] / [someone else]
- AI_CONTEXT_MESSAGES=0 sends the flagged message alone, as before
- Prompt explains the context and treats a lone swear word as an
  exclamation; examples and tools/ai_eval.py (38 cases) cover it

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- ai_chat.py: Workers AI chat on its own background thread; short plain-text
  answers for screen readers (Markdown stripped), in the question's language
- A channel message starting with the AI_CHAT_PREFIX ("@ai" followed by a
  space, ':' or ',') is forwarded; the answer is posted in that channel as
  "[AI] untuk <nick>: ..." plus AI_CHAT_DISCLAIMER. As an admin the bot posts
  without joining the channel, so there are no join/leave sounds
- Follow-ups: the channel's last AI_CHAT_HISTORY questions/answers from the
  last 10 minutes go along; nicknames are never sent to the AI
- Per-person cooldown and a daily limit (told privately); answers with a
  clear badword are replaced by a refusal; failures get a short apology
- Channel messages are intercepted while it is on; /abt aichat (off by
  default, refused without credentials); /help ai for users
- ai_review: the HTTP call is shared as call_workers_ai()

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@raf-li
raf-li merged commit 46d2d0f into main Oct 5, 2026
2 checks passed
@raf-li
raf-li deleted the feature/ai-channel-chat branch October 5, 2026 00:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant