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:
asepharyana
2026-08-16 19:56:27 +07:00
parent 4cf5b87f2b
commit aa280c48b7
7 changed files with 39 additions and 81 deletions
@@ -217,6 +217,14 @@ export const configSchema = z
.default(true),
// Max glossary terms looked up per analysis batch (keeps latency bounded).
AI_GLOSSARY_MAX_TERMS: z.coerce.number().int().min(1).max(20).default(6),
// Per-user personal profile summaries (userProfileLearner). Disabled by
// default: profiles bloat the analysis context and add LLM/DB cost for
// little moderation signal — only <user_reputation> history is injected.
AI_USER_PROFILE_LEARNING_ENABLED: z
.string()
.optional()
.transform((v) => v === "true")
.default(false),
// Min word length for a term to be considered glossary-worthy.
AI_GLOSSARY_MIN_WORD_LENGTH: z.coerce
.number()