UNPKG

askexperts

Version:

AskExperts SDK: build and use AI experts - ask them questions and pay with bitcoin on an open protocol

113 lines 4.97 kB
import { SimplePool } from "nostr-tools"; import { getDocstore, createDocstoreClient, } from "../index.js"; import { Nostr } from "../../../../experts/utils/Nostr.js"; import { debugError, debugDocstore, enableAllDebug, } from "../../../../common/debug.js"; import { createRagEmbeddings } from "../../../../rag/index.js"; /** * Import Nostr events into a docstore * @param author - Nostr pubkey to import events from * @param options - Command options */ export async function importNostr(author, options) { try { // Enable debug output if debug flag is set if (options.debug) { enableAllDebug(); } const docstoreClient = await createDocstoreClient(options); // Get docstore ID const docstore = await getDocstore(docstoreClient, options.docstore); // Parse kinds if provided const kinds = options.kinds ? options.kinds.split(",").map((k) => parseInt(k.trim(), 10)) : []; // Parse relays if provided const relays = options.relays ? options.relays.split(",").map((r) => r.trim()) : []; // Set limit const limit = options.limit || 1000; debugDocstore(`Importing Nostr events for pubkey: ${author}`); debugDocstore(`Kinds: ${kinds.length > 0 ? kinds.join(", ") : "Default (1)"}`); debugDocstore(`Limit: ${limit}`); // Create SimplePool and Nostr utility instance const pool = new SimplePool(); const nostr = new Nostr(pool); // Crawl events using the Nostr utility class const events = await nostr.crawl({ pubkey: author, kinds, relays, limit, }); // Clean up pool connections pool.destroy(); debugDocstore(`Fetched ${events.length} events. Preparing embeddings...`); // Initialize embeddings const embeddings = createRagEmbeddings(docstore.model); await embeddings.start(); // Process each event let successCount = 0; for (const event of events) { try { // Convert event to text, only take content and text as the // rest is probably noise const eventText = JSON.stringify([event.content, ...event.tags]); // Generate embeddings const chunks = await embeddings.embed(eventText); // Convert embeddings from number[][] to Float32Array[] const float32Embeddings = chunks.map((c) => { const float32Array = new Float32Array(c.embedding.length); for (let i = 0; i < c.embedding.length; i++) { float32Array[i] = c.embedding[i]; } return float32Array; }); // Create document const timestamp = Math.floor(Date.now() / 1000); const doc = { id: event.id, docstore_id: docstore.id, timestamp: timestamp, created_at: event.created_at, type: `nostr:kind:${event.kind}`, data: JSON.stringify(event), embeddings: float32Embeddings, }; // Add to docstore await docstoreClient.upsert(doc); successCount++; // Log progress if (successCount % 10 === 0) { debugDocstore(`Processed ${successCount}/${events.length} events`); } } catch (error) { debugError(`Error processing event ${event.id}: ${error instanceof Error ? error.message : String(error)}`); } } debugDocstore(`Successfully imported ${successCount} Nostr events`); docstoreClient[Symbol.dispose](); } catch (error) { debugError(`Error importing Nostr events: ${error instanceof Error ? error.message : String(error)}`); process.exit(1); } } /** * Register the nostr import command * @param importCommand - The parent import command */ export function registerNostrImportCommand(importCommand, addCommonOptions) { const nostrCommand = importCommand .command("nostr") .description("Import Nostr events from a pubkey") .argument("<author>", "Nostr pubkey to import events from") .option("-s, --docstore <id>", "ID of the docstore (required if more than one docstore exists)") .option("-k, --kinds <kinds>", "Comma-separated list of event kinds to import") .option("--relays <relays>", "Comma-separated list of relays to fetch from") .option("-l, --limit <limit>", "Maximum number of events to import (default: 1000)", (value) => parseInt(value, 10)) .action(importNostr); addCommonOptions(nostrCommand); } //# sourceMappingURL=nostr.js.map