Add KI/LLM integration with OpenAI-compatible API support
All checks were successful
Auto Build and Push Docker Image / build (push) Successful in 30s
All checks were successful
Auto Build and Push Docker Image / build (push) Successful in 30s
Features: - /ai setup - Setup wizard via private chat for security - /ai status - Show current config (API key masked) - /ai on/off - Enable/disable AI per chat - /ai random <1-10> - Set random trigger probability (admins) - /ai help - Detailed help - /ask-ai [text] - Generate AI response Security: - API keys only entered in private chat - API keys masked in status display - Admin-only configuration Architecture: - OpenAI-compatible client (OpenAI, Ollama, OpenRouter) - Global system prompt (.env) + group prompt (DB) - 50 message context per chat - SQLite tables: ai_settings, message_context, setup_sessions Defaults: - AI disabled by default - Trigger word: ask-ai - Random probability: 1% Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
110
CLAUDE.md
110
CLAUDE.md
@@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||
|
||||
## Project Overview
|
||||
|
||||
Telegram bot built with TypeScript and [Telegraf](https://telegraf.js.org/). Uses Markov chains with trigrams to generate sentences from learned messages. Each chat has its own isolated Markov chain, creating unique "personalities" per group.
|
||||
Telegram bot built with TypeScript and [Telegraf](https://telegraf.js.org/). Uses Markov chains with trigrams to generate sentences from learned messages. Optional KI/LLM integration via OpenAI-compatible API. Each chat has its own isolated data.
|
||||
|
||||
## Commands
|
||||
|
||||
@@ -19,75 +19,97 @@ docker compose up -d --build # Docker deployment
|
||||
|
||||
```
|
||||
src/
|
||||
├── index.ts # Bot entry point, commands, message handling
|
||||
├── index.ts # Bot entry point, commands, setup wizard
|
||||
├── markov.ts # Markov chain with trigram support
|
||||
└── database.ts # SQLite persistence layer
|
||||
├── database.ts # SQLite persistence layer
|
||||
└── ai.ts # OpenAI-compatible client
|
||||
```
|
||||
|
||||
**Data flow:**
|
||||
**Data flow (Markov):**
|
||||
1. Message received → `chain.learn(text)` → SQLite
|
||||
2. Trigger check (reply/mention/random)
|
||||
3. If triggered → `chain.generate()` → reply
|
||||
|
||||
**Data flow (AI):**
|
||||
1. `/ask-ai` or trigger word detected
|
||||
2. Load last 50 messages as context
|
||||
3. Build prompt (global + group prompt)
|
||||
4. Call OpenAI-compatible API → reply
|
||||
|
||||
**Per-chat isolation:**
|
||||
- Each chat has separate Markov chain data
|
||||
- Each chat has its own response probability setting
|
||||
- In-memory cache (`chains` Map) loaded lazily from DB
|
||||
- Each chat has separate AI settings
|
||||
- Each chat has separate message context (50 messages)
|
||||
|
||||
## Key Implementation Details
|
||||
|
||||
### Markov Chain (markov.ts)
|
||||
- Uses **trigrams** (order=2): "word1 word2" → "word3"
|
||||
- Better grammatical coherence than bigrams
|
||||
- Weighted random selection based on frequency
|
||||
- Generates sentences up to 20 words
|
||||
|
||||
### Database (database.ts)
|
||||
- SQLite with `better-sqlite3` (synchronous API)
|
||||
- Three tables: `chat_settings`, `markov_transitions`, `markov_starts`
|
||||
- Transactions for atomic updates
|
||||
- Tables:
|
||||
- `chat_settings` - Markov probability
|
||||
- `markov_transitions` - Word transitions
|
||||
- `markov_starts` - Sentence starts
|
||||
- `ai_settings` - KI configuration per chat
|
||||
- `message_context` - Last 50 messages per chat
|
||||
- `setup_sessions` - Setup wizard state
|
||||
- Automatic cleanup every 24h
|
||||
|
||||
### Cleanup Mechanism
|
||||
```typescript
|
||||
const MAX_TRANSITIONS_PER_CHAT = 10000; // Upper limit
|
||||
const MIN_TRANSITION_COUNT = 2; // Remove rare entries
|
||||
const MIN_TRANSITIONS_TO_CLEANUP = 100; // Protect new chats
|
||||
```
|
||||
### AI Client (ai.ts)
|
||||
- OpenAI-compatible API (works with OpenAI, Ollama, OpenRouter, etc.)
|
||||
- Prompt system: Global (.env) + Group-specific (DB)
|
||||
- API key masking for security
|
||||
- Context: Last 50 messages
|
||||
|
||||
### Response Triggers
|
||||
1. Reply to bot's message → always respond
|
||||
2. @username mention → always respond
|
||||
3. Random probability (default 10%) in groups
|
||||
4. Always respond in private chats
|
||||
### Setup Wizard
|
||||
- Started via `/ai setup` in group
|
||||
- Continues in private chat for security
|
||||
- API keys never shown in full
|
||||
- Steps: Provider → API Key → Model → URL → Trigger/Prob → Group Prompt
|
||||
|
||||
## Environment
|
||||
|
||||
- `BOT_TOKEN` - Telegram bot token (required)
|
||||
- Database: `data/ulfbot.db` (auto-created)
|
||||
|
||||
## Docker
|
||||
|
||||
- Uses `node:20-slim` for better-sqlite3 compatibility
|
||||
- Volume `ulfbot-data` mounts to `/app/data`
|
||||
- Build locally: `npm run build` then `docker compose up -d --build`
|
||||
|
||||
## Common Modifications
|
||||
|
||||
**Change response probability default:**
|
||||
```typescript
|
||||
// database.ts
|
||||
return { probability: (row?.probability ?? 10) }; // Change default
|
||||
```env
|
||||
BOT_TOKEN= # Telegram bot token (required)
|
||||
AI_DEFAULT_API_KEY= # Default API key (optional)
|
||||
AI_DEFAULT_BASE_URL= # Default API URL (default: OpenAI)
|
||||
AI_DEFAULT_MODEL= # Default model (default: gpt-4o-mini)
|
||||
AI_SYSTEM_PROMPT= # Global system prompt
|
||||
```
|
||||
|
||||
**Change cleanup interval:**
|
||||
```typescript
|
||||
// index.ts
|
||||
const CLEANUP_INTERVAL_MS = 24 * 60 * 60 * 1000; // Currently 24h
|
||||
## Database Schema
|
||||
|
||||
```sql
|
||||
-- Markov
|
||||
chat_settings (chat_id, probability)
|
||||
markov_transitions (chat_id, key, next_word, count)
|
||||
markov_starts (chat_id, key, count)
|
||||
|
||||
-- AI
|
||||
ai_settings (chat_id, enabled, trigger_word, random_prob, group_prompt, provider, base_url, model, api_key)
|
||||
message_context (chat_id, role, content, timestamp)
|
||||
setup_sessions (user_id, chat_id, step, data)
|
||||
```
|
||||
|
||||
**Change Markov order (affects grammar quality):**
|
||||
```typescript
|
||||
// markov.ts
|
||||
constructor(order: number = 2) // Higher = better grammar, needs more data
|
||||
```
|
||||
## Response Triggers
|
||||
|
||||
### Markov (always active)
|
||||
1. Reply to bot's message → always respond
|
||||
2. @username mention → always respond
|
||||
3. Random probability (configurable per chat)
|
||||
|
||||
### AI (when enabled)
|
||||
1. `/ask-ai [text]` command
|
||||
2. Trigger word (configurable, default: "ask-ai")
|
||||
3. Random probability (configurable, default: 0%)
|
||||
|
||||
## Security
|
||||
|
||||
- API keys stored in database, never logged
|
||||
- API keys masked in `/ai status` output: `sk-***...***xyz`
|
||||
- Setup only via private chat
|
||||
- Admin-only configuration commands
|
||||
Reference in New Issue
Block a user