Gateway @/ alias imports use no .js extension (relative imports keep .js). The .js suffix on @/ paths caused double-extension ERR_MODULE_NOT_FOUND (embeddingClient.js.js) at runtime.
64 lines
1.9 KiB
TypeScript
64 lines
1.9 KiB
TypeScript
import { embedText } from "@/modules/ai-moderation/embeddingClient";
|
|
import {
|
|
ARCHIVE_COLLECTION,
|
|
qdrantPointId,
|
|
upsertQdrantPointV2,
|
|
} from "@/modules/ai-moderation/qdrantClient";
|
|
import { config } from "../../shared/config/config.js";
|
|
import { createChildLogger } from "@/shared/logger/index";
|
|
|
|
const log = createChildLogger("archive-embedder");
|
|
|
|
export interface ArchiveMessage {
|
|
id: string;
|
|
content: string;
|
|
username: string;
|
|
channel_id: string;
|
|
guild_id: string;
|
|
created_at: number;
|
|
}
|
|
|
|
/**
|
|
* Fire-and-forget: embed a captured message and upsert it into the persistent
|
|
* archive collection so the public web can semantic-search the corpus.
|
|
*
|
|
* Failures are swallowed — searching is a nice-to-have, never a precondition
|
|
* for capture or moderation. The message text is kept in the payload so the
|
|
* search endpoint can return results even for deleted messages.
|
|
*/
|
|
export function archiveMessageEmbedded(message: ArchiveMessage): void {
|
|
if (!config.AI_LLM_EMBEDDING_MODEL) return; // embeddings disabled → skip
|
|
const text = message.content?.trim();
|
|
if (!text || text.length < 3) return;
|
|
|
|
void (async () => {
|
|
try {
|
|
const vector = await embedText(text);
|
|
if (!vector) return;
|
|
const ok = await upsertQdrantPointV2(
|
|
ARCHIVE_COLLECTION,
|
|
qdrantPointId(`archive:${message.id}`),
|
|
vector,
|
|
{
|
|
text: text.slice(0, 4000),
|
|
flags: "",
|
|
analyzed_at: Date.now(),
|
|
// 5-year persistent window (archive is NOT a TTL cache).
|
|
expires_at: Date.now() + 1000 * 60 * 60 * 24 * 365 * 5,
|
|
content_hash: message.id,
|
|
},
|
|
);
|
|
if (!ok) return;
|
|
log.debug({ messageId: message.id }, "Archived message embedding");
|
|
} catch (err) {
|
|
log.debug(
|
|
{
|
|
messageId: message.id,
|
|
error: err instanceof Error ? err.message : String(err),
|
|
},
|
|
"archive embed skipped",
|
|
);
|
|
}
|
|
})();
|
|
}
|