perf(ai-moderation): remove per-user reputation from analysis context

User: 'jangan ada reputasi juga' — no profile, no reputation in the prompt,
raw messages only.

- textBatchProcessor: drop initializeUserReputation fetch + <user_reputation>
  tag injection (kept the minimal <message> tag + reply/reference context).
- visionAnalyzer (prepareMediaMessage): same removal.
- prompts/system.ts + prompts/output.ts: replace <user_reputation>/<user_history>
  instructions with an explicit 'no per-user profile/reputation context'
  note so the LLM judges purely on message content + conversation/web/location.
- mediaBatchProcessor: fix stale comment.

Trust/infraction state is STILL written to the DB (userReputationsTable) for
enforcement — only the LLM context injection is removed, so moderation
actions (mute/ban via infraction thresholds) keep working.

Net: even smaller prompts (no per-user context at all) → more messages fit
per request, and one fewer DB round-trip per unique user per sub-batch.

tsc, biome, vitest (129) all clean.
This commit is contained in:
asepharyana
2026-08-16 20:44:39 +07:00
parent aa280c48b7
commit 2825250804
5 changed files with 17 additions and 40 deletions
@@ -64,7 +64,6 @@ import {
import {
buildReferenceXml,
escapeXml,
formatReputationAttrs,
getAnalysisContent,
resolveDisplayName,
resolveIsBot,
@@ -84,7 +83,6 @@ import {
} from "./searxngSearch.js";
import { buildTermGlossaryBlock } from "./termGlossary.js";
import { extractUrlsFromText } from "./urlFetcher.js";
import { initializeUserReputation } from "./userReputationStore.js";
// ---------------------------------------------------------------------------
// Types
@@ -398,15 +396,13 @@ export async function prepareMediaMessage(
.filter(Boolean)
.join(" ");
const rep = await initializeUserReputation(target.user_id, target.guild_id);
const refXml = await buildReferenceXml(target);
// Only the behavioural <user_reputation> history is injected; personal profile descriptions are omitted (see textBatchProcessor).
const repAttrs = formatReputationAttrs(rep);
const repXml = `<user_reputation ${repAttrs}/>`;
// No per-user reputation/profile context is injected into the prompt —
// keep the AI analysis context minimal (raw messages only). Trust state is
// still tracked in the DB for enforcement, just not shown to the LLM.
const isBot = resolveIsBot(target);
const isEdited = resolveIsEdited(target);
const messageBlock = `<message id="${escapeXml(target.id)}" user="${escapeXml(resolveDisplayName(target))}" time="${new Date(target.created_at).toISOString()}"${isBot ? ` bot="true"` : ""}${isEdited ? ` edited="true"` : ""}>\n ${repXml}${refXml ? `\n ${refXml}` : ""}\n <content>${escapeXml(truncateForAi(content))}</content>${mediaContext ? ` ${escapeXml(mediaContext)}` : ""}${webContext}${mediaAnalysisContext}${searxngXml}${glossaryCtx}\n</message>`;
const messageBlock = `<message id="${escapeXml(target.id)}" user="${escapeXml(resolveDisplayName(target))}" time="${new Date(target.created_at).toISOString()}"${isBot ? ` bot="true"` : ""}${isEdited ? ` edited="true"` : ""}>\n ${refXml ? `\n ${refXml}` : ""}\n <content>${escapeXml(truncateForAi(content))}</content>${mediaContext ? ` ${escapeXml(mediaContext)}` : ""}${webContext}${mediaAnalysisContext}${searxngXml}${glossaryCtx}\n</message>`;
return { targetId, messageBlock };
}