UNPKG

@gaiaverse/semantic-turning-point-detector

Version:

Detects key semantic turning points in conversations using recursive semantic distance analysis. Ideal for conversation analysis, dialogue segmentation, insight detection, and AI-assisted reasoning tasks.

281 lines 11.5 kB
import { ResponseFormatJSONSchema } from 'openai/resources/shared'; import { type Message } from './Message'; /** * Message span identifies a range of messages * Used for tracking dimensional representations across recursion levels */ interface MessageSpan { /** Start message ID */ startId: string; /** End message ID */ endId: string; /** Start index in the original message array */ startIndex: number; /** End index in the original message array */ endIndex: number; /** Original message span if this is a meta-message span */ originalSpan?: MessageSpan; } /** * Represents a semantic turning point in a conversation * This corresponds to a significant semantic shift detected by the system */ export interface TurningPoint { /** Unique identifier for this turning point */ id: string; /** Human-readable short description of what this turning point represents */ label: string; /** The type of semantic shift this turning point represents */ category: TurningPointCategory; /** The span of messages covered by this turning point */ span: MessageSpan; /** Legacy span format no longer utilized due to new class instantiations for MetaMessages */ deprecatedSpan?: { startIndex: number; endIndex: number; startMessageId: string; endMessageId: string; }; /** The semantic distance/shift that triggered this turning point */ semanticShiftMagnitude: number; /** Key terms that characterize this turning point */ keywords?: string[]; /** Notable quotes from the messages in this turning point's span */ quotes?: string[]; /** The emotionality of this turning point if applicable */ emotionalTone?: string; /** * The dimension at which this turning point was detected. * If detectionLevel > 0, it indicates that this turning point was analyzed based on a span of turning points, rather than a span of messages. */ detectionLevel: number; /** Significance score (higher = more significant) */ significance: number; /** An assessed best point representing the turning point */ /** The complexity score (1-5) representing saturation in current dimension */ complexityScore: number; /** * A potential label assigned by the LLM, which can be either 'positive' or 'negative'. * However, this label is not definitive and may be improved using a zero-shot model, * based on the classification provided by the LLM. */ sentiment?: string; } /** * Categories of turning points */ export type TurningPointCategory = 'Topic' | 'Insight' | 'Emotion' | 'Meta-Reflection' | 'Decision' | 'Question' | 'Problem' | 'Action' | 'Clarification' | 'Objection' | 'Other'; /** * Configuration options for the turning point detector */ export interface TurningPointDetectorConfig { /** OpenAI API key */ apiKey: string; /** Model for turning point classification */ classificationModel: string; /** Model for generating embeddings, e.g 'text-embedding-3-small', or some model custom, from a configurable openai api compatible endpoint v1/embeddings endpoint */ embeddingModel: string; /** Settable openai compatible embedding endpoint */ embeddingEndpoint?: string; /** Semantic shift threshold for detecting potential turning points */ semanticShiftThreshold: number; /** Minimum tokens per chunk when processing conversation */ minTokensPerChunk: number; /** Maximum tokens per chunk */ maxTokensPerChunk: number; /** Maximum recursive depth (dimensional expansion limit) */ maxRecursionDepth: number; /** Whether to filter by significance */ onlySignificantTurningPoints: boolean; /** Significance threshold for filtering */ significanceThreshold: number; /** Minimum messages per chunk */ minMessagesPerChunk: number; /** Maximum turning points in final results */ maxTurningPoints: number; /** Enable verbose logging */ debug: boolean; /** Custom OpenAI API endpoint (optional) */ endpoint?: string; /** Complexity saturation threshold (dimension escalation trigger) */ complexitySaturationThreshold: number; /** Enable convergence measurement across iterations */ measureConvergence: boolean; customResponseFormatJsonSchema?: ResponseFormatJSONSchema; /** Inject a custom system instruction into the LLM prompt, not recommended unless you know what you are doing * - Will repeat your system instruction after the contextual aid text, and before the system prompt ending. * - This enforces and reminds the llm of the task, which may become blured from the contextual aid text. */ customSystemInstruction?: string; /** * Inject a custom user message into the LLM prompt, in which the analysis content is added as context. * - Not recommended unless you know what you are doing. * - Repeats your custom user message after the system prompt ending. */ customUserInstruction?: string; /** The maximum number of characters to use when adding a message content as context to analyze */ max_character_length?: number; /** * This option determines whether to fail and halt the process if an analysis * encounters an error during a potential turning point. * * - Instead of returning a placeholder for an empty analysis that will be ignored, * the process will stop on failure. * - This option is provided because, although an analysis may fail, * it is important to consider that the analysis spans multiple message intervals. * A single failure in one interval is treated the same as an analysis * that does not indicate a significant turning point. * - This is useful, as one may debug and discover the appropriate settings for the llm request, and once discovered would set this to true, or incorporate a retry mechanism. */ throwOnError?: boolean; } /** * Tracks state changes across iteration for convergence measurement */ interface ConvergenceState { /** Previous state turning points */ previousTurningPoints: TurningPoint[]; /** Current state turning points */ currentTurningPoints: TurningPoint[]; /** Current dimension */ dimension: number; /** Convergence measure between states (lower = more converged) */ distanceMeasure: number; /** Whether the state has converged */ hasConverged: boolean; /** Whether dimension escalation occurred */ didEscalate: boolean; } export declare class SemanticTurningPointDetector { private config; private openai; private originalMessages; private convergenceHistory; /** * Creates a new instance of the semantic turning point detector */ constructor(config?: Partial<TurningPointDetectorConfig>); /** * Main entry point: Detect turning points in a conversation * Implements the full ARC/CRA framework */ detectTurningPoints(messages: Message[]): Promise<TurningPoint[]>; /** * Multi-layer detection implementing the ARC/CRA dimensional processing * This is the primary implementation of the transition operator Ψ */ private multiLayerDetection; /** * Calculate a difference measure between two states (sets of turning points) * Used for convergence tracking. Considers significance and location. */ private calculateStateDifference; /** * Apply complexity function χ from the ARC/CRA framework */ private calculateComplexityScore; /** * Detect turning points within a single chunk of the conversation */ /** * Detect turning points within a single chunk of the conversation * This represents the local refinement process in the current dimension */ private detectTurningPointsInChunk; /** * Use LLM to classify a turning point and generate metadata. * *** MODIFIED to prioritize message.spanData over regex *** */ private classifyTurningPoint; /** * Updated to utilize new classes of Message and MetaMessage for better structure and clarity * @param turningPoints * @param originalMessages * @returns */ private createMetaMessagesFromTurningPoints; /** * Filter turning points to keep only significant ones * (Using original logic from the second code block) */ private filterSignificantTurningPoints; /** * Combine turning points from different dimensions * (Using original logic from the second code block) */ private combineTurningPoints; /** * Merge similar or overlapping turning points *within* the same dimension * (Using original logic from the second code block) */ private mergeSimilarTurningPoints; /** * Merge turning points across different dimensions with priority to higher dimensions * (Using original logic from the second code block) */ private mergeAcrossLevels; /** * Create a merged label (Using original logic) */ private createMergedLabel; /** * Find common significant words (Using original logic) */ private findCommonWords; /** * Get a unique key for a message span (Using original logic) */ private getSpanKey; /** * Check if a span overlaps with any spans in the covered set (Using original logic) * Note: This might be less accurate than the index-based check in mergeAcrossLevels now. * Kept for potential use by filterSignificantTurningPoints if it uses range strings. */ private isSpanOverlapping; /** * Generate embeddings for an array of messages (Using original logic) */ private generateMessageEmbeddings; /** * Retrieves the embedding for a given text string. * * - Utilizes the configured embedding model. * - If the model is not an OpenAI model, it uses the OpenAI client with an optional endpoint. * - If the model is an OpenAI model, it creates a new OpenAI client to ensure the correct endpoint is used. */ private getEmbedding; /** * Calculate semantic distance (Using original logic with sigmoid adjustment) */ private calculateSemanticDistance; /** * Chunk a conversation (Using original logic) */ private chunkConversation; /** * Ensures a message span is in chronological order by index * (Using original logic) */ private ensureChronologicalSpan; /** * Get token count for a message with caching (Using original logic) */ private getMessageTokenCount; /** * Get token count for multiple messages (Using original logic) */ getMessageArrayTokenCount(messages: Message[]): Promise<number>; /** * Get the convergence history for analysis (Using original logic) */ getConvergenceHistory(): ConvergenceState[]; private prepareContextualInfoMeta; /** * Prepares contextual information to be appended to the LLM prompt. * Gathers nearby messages (before, after, and within the span) for additional context. * - This preperation is soley meant for dimension at 0, wherein the messages are still base level messages, rather than MetaMessages, which encompass a group of turning points. */ private prepareContextualInfoMessage; } export {}; //# sourceMappingURL=semanticTurningPointDetector.d.ts.map