perf(ai-moderation): drop personal user-profile descriptions from context
User insight: personal profile summaries bloat the prompt (less room per request) and add a per-user DB/Redis round-trip for little moderation signal. Only the behavioural <user_reputation> history is kept. - textBatchProcessor: stop fetching getUserProfile; remove <user_profiles> block + <user_profile_ref> from message tags. Keep <user_reputation>. - mediaBatchProcessor + visionAnalyzer: same removal (profile fetch + ref). - prompts/system.ts + prompts/output.ts: drop stale <user_profiles>/ <user_profile_ref> instructions; point LLM at <user_reputation> instead. - aiAnalyzer: gate userProfileLearner behind AI_USER_PROFILE_LEARNING_ENABLED (default false) — generates profiles nobody reads, pure LLM/DB waste. - Add AI_USER_PROFILE_LEARNING_ENABLED config knob. Net: smaller prompts (more messages fit per request), fewer DB round-trips per sub-batch, and no background LLM calls learning unused profiles. tsc, biome, vitest (129) all clean.
This commit is contained in:
@@ -63,7 +63,6 @@ import {
|
||||
} from "./mediaDownloader.js";
|
||||
import {
|
||||
buildReferenceXml,
|
||||
buildUserProfileRef,
|
||||
escapeXml,
|
||||
formatReputationAttrs,
|
||||
getAnalysisContent,
|
||||
@@ -85,7 +84,6 @@ import {
|
||||
} from "./searxngSearch.js";
|
||||
import { buildTermGlossaryBlock } from "./termGlossary.js";
|
||||
import { extractUrlsFromText } from "./urlFetcher.js";
|
||||
import { getUserProfile } from "./userProfileStore.js";
|
||||
import { initializeUserReputation } from "./userReputationStore.js";
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -401,21 +399,14 @@ export async function prepareMediaMessage(
|
||||
.join(" ");
|
||||
|
||||
const rep = await initializeUserReputation(target.user_id, target.guild_id);
|
||||
const profile = await getUserProfile(target.user_id);
|
||||
const refXml = await buildReferenceXml(target);
|
||||
// Profile is emitted ONCE per batch in a <user_profiles> map (see
|
||||
// mediaBatchProcessor); here we only reference it to avoid repeating the
|
||||
// full summary on every message of the same user.
|
||||
const profileRef = profile?.profile_summary?.trim()
|
||||
? buildUserProfileRef(target.user_id)
|
||||
: "";
|
||||
|
||||
// Rich reputation — attrs only, no user history injection (per channel context preference)
|
||||
// Only the behavioural <user_reputation> history is injected; personal profile descriptions are omitted (see textBatchProcessor).
|
||||
const repAttrs = formatReputationAttrs(rep);
|
||||
const repXml = `<user_reputation ${repAttrs}/>`;
|
||||
|
||||
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}${profileRef ? `\n ${profileRef}` : ""}${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 ${repXml}${refXml ? `\n ${refXml}` : ""}\n <content>${escapeXml(truncateForAi(content))}</content>${mediaContext ? ` ${escapeXml(mediaContext)}` : ""}${webContext}${mediaAnalysisContext}${searxngXml}${glossaryCtx}\n</message>`;
|
||||
return { targetId, messageBlock };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user