@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
TypeScript
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