Zulassen von Anonymen RFID updates verlinkung der UUID wenn spieler angelegt wurde
This commit is contained in:
253
config/llm-blacklist.js
Normal file
253
config/llm-blacklist.js
Normal file
@@ -0,0 +1,253 @@
|
||||
/**
|
||||
* LLM-basierte Blacklist-Prüfung mit Ollama
|
||||
* Verwendet ein lokales LLM zur intelligenten Bewertung von Namen
|
||||
*/
|
||||
|
||||
const axios = require('axios');
|
||||
|
||||
// Ollama-Konfiguration
|
||||
const OLLAMA_BASE_URL = process.env.OLLAMA_BASE_URL || 'http://localhost:11434';
|
||||
const OLLAMA_MODEL = process.env.OLLAMA_MODEL || 'llama3.2:3b'; // Schnelles, kleines Modell
|
||||
|
||||
/**
|
||||
* Prüft einen Namen mit dem LLM
|
||||
* @param {string} firstname - Vorname
|
||||
* @param {string} lastname - Nachname
|
||||
* @returns {Object} - {isBlocked: boolean, reason: string, confidence: number}
|
||||
*/
|
||||
async function checkNameWithLLM(firstname, lastname) {
|
||||
if (!firstname || !lastname) {
|
||||
return { isBlocked: false, reason: '', confidence: 0 };
|
||||
}
|
||||
|
||||
try {
|
||||
const fullName = `${firstname} ${lastname}`;
|
||||
|
||||
// Prompt für das LLM
|
||||
const prompt = `Du bist ein strenger Moderator für ein Spielsystem. Prüfe ob der Name "${fullName}" für die Verwendung geeignet ist.
|
||||
|
||||
WICHTIG: Blockiere ALLE Namen die:
|
||||
- Historisch belastet sind (Adolf Hitler, Stalin, Mussolini, etc.)
|
||||
- Beleidigend oder anstößig sind (Satan, Idiot, etc.)
|
||||
- Unpassende Titel sind (Dr., Professor, etc.)
|
||||
- Markennamen sind (Coca-Cola, Nike, etc.)
|
||||
- Andere unangemessene Inhalte haben
|
||||
|
||||
Antworte NUR mit "TRUE" (blockiert) oder "FALSE" (erlaubt) - keine Erklärungen.
|
||||
|
||||
Name: "${fullName}"
|
||||
Antwort:`;
|
||||
|
||||
// Ollama API-Aufruf
|
||||
const response = await axios.post(`${OLLAMA_BASE_URL}/api/generate`, {
|
||||
model: OLLAMA_MODEL,
|
||||
prompt: prompt,
|
||||
stream: false,
|
||||
options: {
|
||||
temperature: 0.1, // Niedrige Temperatur für konsistente Antworten
|
||||
top_p: 0.9,
|
||||
max_tokens: 10 // Nur TRUE/FALSE erwartet
|
||||
}
|
||||
}, {
|
||||
timeout: 10000 // 10 Sekunden Timeout
|
||||
});
|
||||
|
||||
const llmResponse = response.data.response.trim().toUpperCase();
|
||||
|
||||
// Parse LLM-Antwort
|
||||
let isBlocked = false;
|
||||
let reason = '';
|
||||
let confidence = 0.8; // Standard-Konfidenz für LLM
|
||||
|
||||
if (llmResponse === 'TRUE') {
|
||||
isBlocked = true;
|
||||
reason = 'Name wurde vom KI-Moderator als ungeeignet eingestuft';
|
||||
} else if (llmResponse === 'FALSE') {
|
||||
isBlocked = false;
|
||||
reason = 'Name wurde vom KI-Moderator als geeignet eingestuft';
|
||||
} else {
|
||||
// Fallback bei unerwarteter Antwort
|
||||
console.warn(`Unerwartete LLM-Antwort: "${llmResponse}" für Name: "${fullName}"`);
|
||||
isBlocked = false;
|
||||
reason = 'KI-Moderator konnte Name nicht eindeutig bewerten';
|
||||
confidence = 0.3;
|
||||
}
|
||||
|
||||
return {
|
||||
isBlocked,
|
||||
reason,
|
||||
confidence,
|
||||
llmResponse: llmResponse,
|
||||
matchType: 'llm'
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error checking name with LLM:', error);
|
||||
|
||||
// Fallback bei LLM-Fehlern
|
||||
return {
|
||||
isBlocked: false,
|
||||
reason: 'KI-Moderator nicht verfügbar - Name wurde erlaubt',
|
||||
confidence: 0.1,
|
||||
error: error.message,
|
||||
matchType: 'llm-error'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testet die LLM-Verbindung
|
||||
* @returns {Object} - {connected: boolean, model: string, error?: string}
|
||||
*/
|
||||
async function testLLMConnection() {
|
||||
try {
|
||||
const response = await axios.post(`${OLLAMA_BASE_URL}/api/generate`, {
|
||||
model: OLLAMA_MODEL,
|
||||
prompt: 'Test',
|
||||
stream: false,
|
||||
options: {
|
||||
max_tokens: 1
|
||||
}
|
||||
}, {
|
||||
timeout: 5000
|
||||
});
|
||||
|
||||
return {
|
||||
connected: true,
|
||||
model: OLLAMA_MODEL,
|
||||
baseUrl: OLLAMA_BASE_URL
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
connected: false,
|
||||
model: OLLAMA_MODEL,
|
||||
baseUrl: OLLAMA_BASE_URL,
|
||||
error: error.message
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Erweiterte LLM-Prüfung mit Kontext
|
||||
* @param {string} firstname - Vorname
|
||||
* @param {string} lastname - Nachname
|
||||
* @param {string} context - Zusätzlicher Kontext (optional)
|
||||
* @returns {Object} - Prüfungsergebnis
|
||||
*/
|
||||
async function checkNameWithContext(firstname, lastname, context = '') {
|
||||
if (!firstname || !lastname) {
|
||||
return { isBlocked: false, reason: '', confidence: 0 };
|
||||
}
|
||||
|
||||
try {
|
||||
const fullName = `${firstname} ${lastname}`;
|
||||
|
||||
// Erweiterter Prompt mit Kontext
|
||||
const prompt = `Du bist ein Moderator für ein Spielsystem. Prüfe ob der Name "${fullName}" für die Verwendung geeignet ist.
|
||||
|
||||
Kontext: ${context || 'Standard-Spielname'}
|
||||
|
||||
Beurteile den Namen basierend auf:
|
||||
- Historisch belastete Namen (z.B. Adolf Hitler, Stalin, etc.)
|
||||
- Beleidigende oder anstößige Begriffe
|
||||
- Unpassende Titel oder Berufsbezeichnungen
|
||||
- Markennamen die nicht verwendet werden sollten
|
||||
- Andere unangemessene Inhalte
|
||||
|
||||
Antworte NUR mit "TRUE" oder "FALSE" - keine Erklärungen.
|
||||
|
||||
Name: "${fullName}"
|
||||
Antwort:`;
|
||||
|
||||
const response = await axios.post(`${OLLAMA_BASE_URL}/api/generate`, {
|
||||
model: OLLAMA_MODEL,
|
||||
prompt: prompt,
|
||||
stream: false,
|
||||
options: {
|
||||
temperature: 0.1,
|
||||
top_p: 0.9,
|
||||
max_tokens: 10
|
||||
}
|
||||
}, {
|
||||
timeout: 10000
|
||||
});
|
||||
|
||||
const llmResponse = response.data.response.trim().toUpperCase();
|
||||
|
||||
let isBlocked = false;
|
||||
let reason = '';
|
||||
let confidence = 0.8;
|
||||
|
||||
if (llmResponse === 'TRUE') {
|
||||
isBlocked = true;
|
||||
reason = 'Name wurde vom KI-Moderator als ungeeignet eingestuft';
|
||||
} else if (llmResponse === 'FALSE') {
|
||||
isBlocked = false;
|
||||
reason = 'Name wurde vom KI-Moderator als geeignet eingestuft';
|
||||
} else {
|
||||
console.warn(`Unerwartete LLM-Antwort: "${llmResponse}" für Name: "${fullName}"`);
|
||||
isBlocked = false;
|
||||
reason = 'KI-Moderator konnte Name nicht eindeutig bewerten';
|
||||
confidence = 0.3;
|
||||
}
|
||||
|
||||
return {
|
||||
isBlocked,
|
||||
reason,
|
||||
confidence,
|
||||
llmResponse: llmResponse,
|
||||
matchType: 'llm-context',
|
||||
context: context
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error checking name with LLM context:', error);
|
||||
|
||||
return {
|
||||
isBlocked: false,
|
||||
reason: 'KI-Moderator nicht verfügbar - Name wurde erlaubt',
|
||||
confidence: 0.1,
|
||||
error: error.message,
|
||||
matchType: 'llm-error'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch-Prüfung mehrerer Namen
|
||||
* @param {Array} names - Array von {firstname, lastname} Objekten
|
||||
* @returns {Array} - Array von Prüfungsergebnissen
|
||||
*/
|
||||
async function checkNamesBatch(names) {
|
||||
const results = [];
|
||||
|
||||
for (const name of names) {
|
||||
try {
|
||||
const result = await checkNameWithLLM(name.firstname, name.lastname);
|
||||
results.push({
|
||||
...name,
|
||||
...result
|
||||
});
|
||||
} catch (error) {
|
||||
results.push({
|
||||
...name,
|
||||
isBlocked: false,
|
||||
reason: 'Fehler bei der Prüfung',
|
||||
confidence: 0,
|
||||
error: error.message,
|
||||
matchType: 'error'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
checkNameWithLLM,
|
||||
checkNameWithContext,
|
||||
checkNamesBatch,
|
||||
testLLMConnection,
|
||||
OLLAMA_BASE_URL,
|
||||
OLLAMA_MODEL
|
||||
};
|
||||
Reference in New Issue
Block a user