@llamaindex/core
Advanced tools
| Object.defineProperty(exports, '__esModule', { value: true }); | ||
| var index_cjs$1 = require('../global/index.cjs'); | ||
| var index_cjs$2 = require('../storage/chat-store/index.cjs'); | ||
| var index_cjs = require('../utils/index.cjs'); | ||
| var env = require('@llamaindex/env'); | ||
| var index_cjs$3 = require('../prompts/index.cjs'); | ||
| const DEFAULT_TOKEN_LIMIT_RATIO = 0.75; | ||
| const DEFAULT_CHAT_STORE_KEY = "chat_history"; | ||
| /** | ||
| * A ChatMemory is used to keep the state of back and forth chat messages | ||
| */ class BaseMemory { | ||
| _tokenCountForMessages(messages) { | ||
| if (messages.length === 0) { | ||
| return 0; | ||
| } | ||
| const tokenizer = index_cjs$1.Settings.tokenizer; | ||
| const str = messages.map((m)=>index_cjs.extractText(m.content)).join(" "); | ||
| return tokenizer.encode(str).length; | ||
| } | ||
| } | ||
| class BaseChatStoreMemory extends BaseMemory { | ||
| constructor(chatStore = new index_cjs$2.SimpleChatStore(), chatStoreKey = DEFAULT_CHAT_STORE_KEY){ | ||
| super(); | ||
| this.chatStore = chatStore; | ||
| this.chatStoreKey = chatStoreKey; | ||
| } | ||
| getAllMessages() { | ||
| return this.chatStore.getMessages(this.chatStoreKey); | ||
| } | ||
| put(messages) { | ||
| this.chatStore.addMessage(this.chatStoreKey, messages); | ||
| } | ||
| set(messages) { | ||
| this.chatStore.setMessages(this.chatStoreKey, messages); | ||
| } | ||
| reset() { | ||
| this.chatStore.deleteMessages(this.chatStoreKey); | ||
| } | ||
| } | ||
| class ChatMemoryBuffer extends BaseChatStoreMemory { | ||
| constructor(options){ | ||
| super(options?.chatStore, options?.chatStoreKey); | ||
| const llm = options?.llm ?? index_cjs$1.Settings.llm; | ||
| const contextWindow = llm.metadata.contextWindow; | ||
| this.tokenLimit = options?.tokenLimit ?? Math.ceil(contextWindow * DEFAULT_TOKEN_LIMIT_RATIO); | ||
| if (options?.chatHistory) { | ||
| this.chatStore.setMessages(this.chatStoreKey, options.chatHistory); | ||
| } | ||
| } | ||
| getMessages(input, initialTokenCount = 0) { | ||
| const messages = this.getAllMessages(); | ||
| if (initialTokenCount > this.tokenLimit) { | ||
| throw new Error("Initial token count exceeds token limit"); | ||
| } | ||
| let messageCount = messages.length; | ||
| let currentMessages = messages.slice(-messageCount); | ||
| let tokenCount = this._tokenCountForMessages(messages) + initialTokenCount; | ||
| while(tokenCount > this.tokenLimit && messageCount > 1){ | ||
| messageCount -= 1; | ||
| if (messages.at(-messageCount).role === "assistant") { | ||
| messageCount -= 1; | ||
| } | ||
| currentMessages = messages.slice(-messageCount); | ||
| tokenCount = this._tokenCountForMessages(currentMessages) + initialTokenCount; | ||
| } | ||
| if (tokenCount > this.tokenLimit && messageCount <= 0) { | ||
| return []; | ||
| } | ||
| return messages.slice(-messageCount); | ||
| } | ||
| } | ||
| class ChatSummaryMemoryBuffer extends BaseMemory { | ||
| constructor(options){ | ||
| super(); | ||
| this.messages = options?.messages ?? []; | ||
| this.summaryPrompt = options?.summaryPrompt ?? index_cjs$3.defaultSummaryPrompt; | ||
| this.llm = options?.llm ?? index_cjs$1.Settings.llm; | ||
| if (!this.llm.metadata.maxTokens) { | ||
| throw new Error("LLM maxTokens is not set. Needed so the summarizer ensures the context window size of the LLM."); | ||
| } | ||
| this.tokenizer = options?.tokenizer ?? env.tokenizers.tokenizer(); | ||
| this.tokensToSummarize = this.llm.metadata.contextWindow - this.llm.metadata.maxTokens; | ||
| if (this.tokensToSummarize < this.llm.metadata.contextWindow * 0.25) { | ||
| throw new Error("The number of tokens that trigger the summarize process are less than 25% of the context window. Try lowering maxTokens or use a model with a larger context window."); | ||
| } | ||
| } | ||
| async summarize() { | ||
| // get the conversation messages to create summary | ||
| const messagesToSummarize = this.calcConversationMessages(); | ||
| let promptMessages; | ||
| do { | ||
| promptMessages = [ | ||
| { | ||
| content: this.summaryPrompt.format({ | ||
| context: index_cjs.messagesToHistory(messagesToSummarize) | ||
| }), | ||
| role: "user", | ||
| options: {} | ||
| } | ||
| ]; | ||
| // remove oldest message until the chat history is short enough for the context window | ||
| messagesToSummarize.shift(); | ||
| }while (this.tokenizer.encode(promptMessages[0].content).length > this.tokensToSummarize) | ||
| const response = await this.llm.chat({ | ||
| messages: promptMessages | ||
| }); | ||
| return { | ||
| content: response.message.content, | ||
| role: "memory" | ||
| }; | ||
| } | ||
| // Find last summary message | ||
| get lastSummaryIndex() { | ||
| const reversedMessages = this.messages.slice().reverse(); | ||
| const index = reversedMessages.findIndex((message)=>message.role === "memory"); | ||
| if (index === -1) { | ||
| return null; | ||
| } | ||
| return this.messages.length - 1 - index; | ||
| } | ||
| getLastSummary() { | ||
| const lastSummaryIndex = this.lastSummaryIndex; | ||
| return lastSummaryIndex ? this.messages[lastSummaryIndex] : null; | ||
| } | ||
| get systemMessages() { | ||
| // get array of all system messages | ||
| return this.messages.filter((message)=>message.role === "system"); | ||
| } | ||
| get nonSystemMessages() { | ||
| // get array of all non-system messages | ||
| return this.messages.filter((message)=>message.role !== "system"); | ||
| } | ||
| /** | ||
| * Calculates the messages that describe the conversation so far. | ||
| * If there's no memory, all non-system messages are used. | ||
| * If there's a memory, uses all messages after the last summary message. | ||
| */ calcConversationMessages(transformSummary) { | ||
| const lastSummaryIndex = this.lastSummaryIndex; | ||
| if (!lastSummaryIndex) { | ||
| // there's no memory, so just use all non-system messages | ||
| return this.nonSystemMessages; | ||
| } else { | ||
| // there's a memory, so use all messages after the last summary message | ||
| // and convert summary message so it can be send to the LLM | ||
| const summaryMessage = transformSummary ? { | ||
| content: `Summary of the conversation so far: ${this.messages[lastSummaryIndex].content}`, | ||
| role: "system" | ||
| } : this.messages[lastSummaryIndex]; | ||
| return [ | ||
| summaryMessage, | ||
| ...this.messages.slice(lastSummaryIndex + 1) | ||
| ]; | ||
| } | ||
| } | ||
| calcCurrentRequestMessages() { | ||
| // TODO: check order: currently, we're sending: | ||
| // system messages first, then transient messages and then the messages that describe the conversation so far | ||
| return [ | ||
| ...this.systemMessages, | ||
| ...this.calcConversationMessages(true) | ||
| ]; | ||
| } | ||
| reset() { | ||
| this.messages = []; | ||
| } | ||
| async getMessages() { | ||
| const requestMessages = this.calcCurrentRequestMessages(); | ||
| // get tokens of current request messages and the transient messages | ||
| const tokens = requestMessages.reduce((count, message)=>count + this.tokenizer.encode(index_cjs.extractText(message.content)).length, 0); | ||
| if (tokens > this.tokensToSummarize) { | ||
| // if there are too many tokens for the next request, call summarize | ||
| const memoryMessage = await this.summarize(); | ||
| const lastMessage = this.messages.at(-1); | ||
| if (lastMessage && lastMessage.role === "user") { | ||
| // if last message is a user message, ensure that it's sent after the new memory message | ||
| this.messages.pop(); | ||
| this.messages.push(memoryMessage); | ||
| this.messages.push(lastMessage); | ||
| } else { | ||
| // otherwise just add the memory message | ||
| this.messages.push(memoryMessage); | ||
| } | ||
| // TODO: we still might have too many tokens | ||
| // e.g. too large system messages or transient messages | ||
| // how should we deal with that? | ||
| return this.calcCurrentRequestMessages(); | ||
| } | ||
| return requestMessages; | ||
| } | ||
| async getAllMessages() { | ||
| return this.getMessages(); | ||
| } | ||
| put(message) { | ||
| this.messages.push(message); | ||
| } | ||
| } | ||
| exports.BaseMemory = BaseMemory; | ||
| exports.ChatMemoryBuffer = ChatMemoryBuffer; | ||
| exports.ChatSummaryMemoryBuffer = ChatSummaryMemoryBuffer; |
| import { MessageContent, ChatMessage, LLM } from '../llms/index.cjs'; | ||
| import { BaseChatStore } from '../storage/chat-store/index.cjs'; | ||
| import { Tokenizer } from '@llamaindex/env'; | ||
| import { SummaryPrompt } from '../prompts/index.cjs'; | ||
| /** | ||
| * A ChatMemory is used to keep the state of back and forth chat messages | ||
| */ | ||
| declare abstract class BaseMemory<AdditionalMessageOptions extends object = object> { | ||
| abstract getMessages(input?: MessageContent | undefined): ChatMessage<AdditionalMessageOptions>[] | Promise<ChatMessage<AdditionalMessageOptions>[]>; | ||
| abstract getAllMessages(): ChatMessage<AdditionalMessageOptions>[] | Promise<ChatMessage<AdditionalMessageOptions>[]>; | ||
| abstract put(messages: ChatMessage<AdditionalMessageOptions>): void; | ||
| abstract reset(): void; | ||
| protected _tokenCountForMessages(messages: ChatMessage[]): number; | ||
| } | ||
| declare abstract class BaseChatStoreMemory<AdditionalMessageOptions extends object = object> extends BaseMemory<AdditionalMessageOptions> { | ||
| chatStore: BaseChatStore<AdditionalMessageOptions>; | ||
| chatStoreKey: string; | ||
| protected constructor(chatStore?: BaseChatStore<AdditionalMessageOptions>, chatStoreKey?: string); | ||
| getAllMessages(): ChatMessage<AdditionalMessageOptions>[]; | ||
| put(messages: ChatMessage<AdditionalMessageOptions>): void; | ||
| set(messages: ChatMessage<AdditionalMessageOptions>[]): void; | ||
| reset(): void; | ||
| } | ||
| type ChatMemoryBufferOptions<AdditionalMessageOptions extends object = object> = { | ||
| tokenLimit?: number | undefined; | ||
| chatStore?: BaseChatStore<AdditionalMessageOptions> | undefined; | ||
| chatStoreKey?: string | undefined; | ||
| chatHistory?: ChatMessage<AdditionalMessageOptions>[] | undefined; | ||
| llm?: LLM<object, AdditionalMessageOptions> | undefined; | ||
| }; | ||
| declare class ChatMemoryBuffer<AdditionalMessageOptions extends object = object> extends BaseChatStoreMemory<AdditionalMessageOptions> { | ||
| tokenLimit: number; | ||
| constructor(options?: Partial<ChatMemoryBufferOptions<AdditionalMessageOptions>>); | ||
| getMessages(input?: MessageContent | undefined, initialTokenCount?: number): ChatMessage<AdditionalMessageOptions>[]; | ||
| } | ||
| declare class ChatSummaryMemoryBuffer extends BaseMemory { | ||
| /** | ||
| * Tokenizer function that converts text to tokens, | ||
| * this is used to calculate the number of tokens in a message. | ||
| */ | ||
| tokenizer: Tokenizer; | ||
| tokensToSummarize: number; | ||
| messages: ChatMessage[]; | ||
| summaryPrompt: SummaryPrompt; | ||
| llm: LLM; | ||
| constructor(options?: Partial<ChatSummaryMemoryBuffer>); | ||
| private summarize; | ||
| private get lastSummaryIndex(); | ||
| getLastSummary(): ChatMessage | null; | ||
| private get systemMessages(); | ||
| private get nonSystemMessages(); | ||
| /** | ||
| * Calculates the messages that describe the conversation so far. | ||
| * If there's no memory, all non-system messages are used. | ||
| * If there's a memory, uses all messages after the last summary message. | ||
| */ | ||
| private calcConversationMessages; | ||
| private calcCurrentRequestMessages; | ||
| reset(): void; | ||
| getMessages(): Promise<ChatMessage[]>; | ||
| getAllMessages(): Promise<ChatMessage[]>; | ||
| put(message: ChatMessage): void; | ||
| } | ||
| export { BaseMemory, ChatMemoryBuffer, ChatSummaryMemoryBuffer }; |
| import { MessageContent, ChatMessage, LLM } from '../llms/index.js'; | ||
| import { BaseChatStore } from '../storage/chat-store/index.js'; | ||
| import { Tokenizer } from '@llamaindex/env'; | ||
| import { SummaryPrompt } from '../prompts/index.js'; | ||
| /** | ||
| * A ChatMemory is used to keep the state of back and forth chat messages | ||
| */ | ||
| declare abstract class BaseMemory<AdditionalMessageOptions extends object = object> { | ||
| abstract getMessages(input?: MessageContent | undefined): ChatMessage<AdditionalMessageOptions>[] | Promise<ChatMessage<AdditionalMessageOptions>[]>; | ||
| abstract getAllMessages(): ChatMessage<AdditionalMessageOptions>[] | Promise<ChatMessage<AdditionalMessageOptions>[]>; | ||
| abstract put(messages: ChatMessage<AdditionalMessageOptions>): void; | ||
| abstract reset(): void; | ||
| protected _tokenCountForMessages(messages: ChatMessage[]): number; | ||
| } | ||
| declare abstract class BaseChatStoreMemory<AdditionalMessageOptions extends object = object> extends BaseMemory<AdditionalMessageOptions> { | ||
| chatStore: BaseChatStore<AdditionalMessageOptions>; | ||
| chatStoreKey: string; | ||
| protected constructor(chatStore?: BaseChatStore<AdditionalMessageOptions>, chatStoreKey?: string); | ||
| getAllMessages(): ChatMessage<AdditionalMessageOptions>[]; | ||
| put(messages: ChatMessage<AdditionalMessageOptions>): void; | ||
| set(messages: ChatMessage<AdditionalMessageOptions>[]): void; | ||
| reset(): void; | ||
| } | ||
| type ChatMemoryBufferOptions<AdditionalMessageOptions extends object = object> = { | ||
| tokenLimit?: number | undefined; | ||
| chatStore?: BaseChatStore<AdditionalMessageOptions> | undefined; | ||
| chatStoreKey?: string | undefined; | ||
| chatHistory?: ChatMessage<AdditionalMessageOptions>[] | undefined; | ||
| llm?: LLM<object, AdditionalMessageOptions> | undefined; | ||
| }; | ||
| declare class ChatMemoryBuffer<AdditionalMessageOptions extends object = object> extends BaseChatStoreMemory<AdditionalMessageOptions> { | ||
| tokenLimit: number; | ||
| constructor(options?: Partial<ChatMemoryBufferOptions<AdditionalMessageOptions>>); | ||
| getMessages(input?: MessageContent | undefined, initialTokenCount?: number): ChatMessage<AdditionalMessageOptions>[]; | ||
| } | ||
| declare class ChatSummaryMemoryBuffer extends BaseMemory { | ||
| /** | ||
| * Tokenizer function that converts text to tokens, | ||
| * this is used to calculate the number of tokens in a message. | ||
| */ | ||
| tokenizer: Tokenizer; | ||
| tokensToSummarize: number; | ||
| messages: ChatMessage[]; | ||
| summaryPrompt: SummaryPrompt; | ||
| llm: LLM; | ||
| constructor(options?: Partial<ChatSummaryMemoryBuffer>); | ||
| private summarize; | ||
| private get lastSummaryIndex(); | ||
| getLastSummary(): ChatMessage | null; | ||
| private get systemMessages(); | ||
| private get nonSystemMessages(); | ||
| /** | ||
| * Calculates the messages that describe the conversation so far. | ||
| * If there's no memory, all non-system messages are used. | ||
| * If there's a memory, uses all messages after the last summary message. | ||
| */ | ||
| private calcConversationMessages; | ||
| private calcCurrentRequestMessages; | ||
| reset(): void; | ||
| getMessages(): Promise<ChatMessage[]>; | ||
| getAllMessages(): Promise<ChatMessage[]>; | ||
| put(message: ChatMessage): void; | ||
| } | ||
| export { BaseMemory, ChatMemoryBuffer, ChatSummaryMemoryBuffer }; |
| import { Settings } from '../global/index.js'; | ||
| import { SimpleChatStore } from '../storage/chat-store/index.js'; | ||
| import { extractText, messagesToHistory } from '../utils/index.js'; | ||
| import { tokenizers } from '@llamaindex/env'; | ||
| import { defaultSummaryPrompt } from '../prompts/index.js'; | ||
| const DEFAULT_TOKEN_LIMIT_RATIO = 0.75; | ||
| const DEFAULT_CHAT_STORE_KEY = "chat_history"; | ||
| /** | ||
| * A ChatMemory is used to keep the state of back and forth chat messages | ||
| */ class BaseMemory { | ||
| _tokenCountForMessages(messages) { | ||
| if (messages.length === 0) { | ||
| return 0; | ||
| } | ||
| const tokenizer = Settings.tokenizer; | ||
| const str = messages.map((m)=>extractText(m.content)).join(" "); | ||
| return tokenizer.encode(str).length; | ||
| } | ||
| } | ||
| class BaseChatStoreMemory extends BaseMemory { | ||
| constructor(chatStore = new SimpleChatStore(), chatStoreKey = DEFAULT_CHAT_STORE_KEY){ | ||
| super(); | ||
| this.chatStore = chatStore; | ||
| this.chatStoreKey = chatStoreKey; | ||
| } | ||
| getAllMessages() { | ||
| return this.chatStore.getMessages(this.chatStoreKey); | ||
| } | ||
| put(messages) { | ||
| this.chatStore.addMessage(this.chatStoreKey, messages); | ||
| } | ||
| set(messages) { | ||
| this.chatStore.setMessages(this.chatStoreKey, messages); | ||
| } | ||
| reset() { | ||
| this.chatStore.deleteMessages(this.chatStoreKey); | ||
| } | ||
| } | ||
| class ChatMemoryBuffer extends BaseChatStoreMemory { | ||
| constructor(options){ | ||
| super(options?.chatStore, options?.chatStoreKey); | ||
| const llm = options?.llm ?? Settings.llm; | ||
| const contextWindow = llm.metadata.contextWindow; | ||
| this.tokenLimit = options?.tokenLimit ?? Math.ceil(contextWindow * DEFAULT_TOKEN_LIMIT_RATIO); | ||
| if (options?.chatHistory) { | ||
| this.chatStore.setMessages(this.chatStoreKey, options.chatHistory); | ||
| } | ||
| } | ||
| getMessages(input, initialTokenCount = 0) { | ||
| const messages = this.getAllMessages(); | ||
| if (initialTokenCount > this.tokenLimit) { | ||
| throw new Error("Initial token count exceeds token limit"); | ||
| } | ||
| let messageCount = messages.length; | ||
| let currentMessages = messages.slice(-messageCount); | ||
| let tokenCount = this._tokenCountForMessages(messages) + initialTokenCount; | ||
| while(tokenCount > this.tokenLimit && messageCount > 1){ | ||
| messageCount -= 1; | ||
| if (messages.at(-messageCount).role === "assistant") { | ||
| messageCount -= 1; | ||
| } | ||
| currentMessages = messages.slice(-messageCount); | ||
| tokenCount = this._tokenCountForMessages(currentMessages) + initialTokenCount; | ||
| } | ||
| if (tokenCount > this.tokenLimit && messageCount <= 0) { | ||
| return []; | ||
| } | ||
| return messages.slice(-messageCount); | ||
| } | ||
| } | ||
| class ChatSummaryMemoryBuffer extends BaseMemory { | ||
| constructor(options){ | ||
| super(); | ||
| this.messages = options?.messages ?? []; | ||
| this.summaryPrompt = options?.summaryPrompt ?? defaultSummaryPrompt; | ||
| this.llm = options?.llm ?? Settings.llm; | ||
| if (!this.llm.metadata.maxTokens) { | ||
| throw new Error("LLM maxTokens is not set. Needed so the summarizer ensures the context window size of the LLM."); | ||
| } | ||
| this.tokenizer = options?.tokenizer ?? tokenizers.tokenizer(); | ||
| this.tokensToSummarize = this.llm.metadata.contextWindow - this.llm.metadata.maxTokens; | ||
| if (this.tokensToSummarize < this.llm.metadata.contextWindow * 0.25) { | ||
| throw new Error("The number of tokens that trigger the summarize process are less than 25% of the context window. Try lowering maxTokens or use a model with a larger context window."); | ||
| } | ||
| } | ||
| async summarize() { | ||
| // get the conversation messages to create summary | ||
| const messagesToSummarize = this.calcConversationMessages(); | ||
| let promptMessages; | ||
| do { | ||
| promptMessages = [ | ||
| { | ||
| content: this.summaryPrompt.format({ | ||
| context: messagesToHistory(messagesToSummarize) | ||
| }), | ||
| role: "user", | ||
| options: {} | ||
| } | ||
| ]; | ||
| // remove oldest message until the chat history is short enough for the context window | ||
| messagesToSummarize.shift(); | ||
| }while (this.tokenizer.encode(promptMessages[0].content).length > this.tokensToSummarize) | ||
| const response = await this.llm.chat({ | ||
| messages: promptMessages | ||
| }); | ||
| return { | ||
| content: response.message.content, | ||
| role: "memory" | ||
| }; | ||
| } | ||
| // Find last summary message | ||
| get lastSummaryIndex() { | ||
| const reversedMessages = this.messages.slice().reverse(); | ||
| const index = reversedMessages.findIndex((message)=>message.role === "memory"); | ||
| if (index === -1) { | ||
| return null; | ||
| } | ||
| return this.messages.length - 1 - index; | ||
| } | ||
| getLastSummary() { | ||
| const lastSummaryIndex = this.lastSummaryIndex; | ||
| return lastSummaryIndex ? this.messages[lastSummaryIndex] : null; | ||
| } | ||
| get systemMessages() { | ||
| // get array of all system messages | ||
| return this.messages.filter((message)=>message.role === "system"); | ||
| } | ||
| get nonSystemMessages() { | ||
| // get array of all non-system messages | ||
| return this.messages.filter((message)=>message.role !== "system"); | ||
| } | ||
| /** | ||
| * Calculates the messages that describe the conversation so far. | ||
| * If there's no memory, all non-system messages are used. | ||
| * If there's a memory, uses all messages after the last summary message. | ||
| */ calcConversationMessages(transformSummary) { | ||
| const lastSummaryIndex = this.lastSummaryIndex; | ||
| if (!lastSummaryIndex) { | ||
| // there's no memory, so just use all non-system messages | ||
| return this.nonSystemMessages; | ||
| } else { | ||
| // there's a memory, so use all messages after the last summary message | ||
| // and convert summary message so it can be send to the LLM | ||
| const summaryMessage = transformSummary ? { | ||
| content: `Summary of the conversation so far: ${this.messages[lastSummaryIndex].content}`, | ||
| role: "system" | ||
| } : this.messages[lastSummaryIndex]; | ||
| return [ | ||
| summaryMessage, | ||
| ...this.messages.slice(lastSummaryIndex + 1) | ||
| ]; | ||
| } | ||
| } | ||
| calcCurrentRequestMessages() { | ||
| // TODO: check order: currently, we're sending: | ||
| // system messages first, then transient messages and then the messages that describe the conversation so far | ||
| return [ | ||
| ...this.systemMessages, | ||
| ...this.calcConversationMessages(true) | ||
| ]; | ||
| } | ||
| reset() { | ||
| this.messages = []; | ||
| } | ||
| async getMessages() { | ||
| const requestMessages = this.calcCurrentRequestMessages(); | ||
| // get tokens of current request messages and the transient messages | ||
| const tokens = requestMessages.reduce((count, message)=>count + this.tokenizer.encode(extractText(message.content)).length, 0); | ||
| if (tokens > this.tokensToSummarize) { | ||
| // if there are too many tokens for the next request, call summarize | ||
| const memoryMessage = await this.summarize(); | ||
| const lastMessage = this.messages.at(-1); | ||
| if (lastMessage && lastMessage.role === "user") { | ||
| // if last message is a user message, ensure that it's sent after the new memory message | ||
| this.messages.pop(); | ||
| this.messages.push(memoryMessage); | ||
| this.messages.push(lastMessage); | ||
| } else { | ||
| // otherwise just add the memory message | ||
| this.messages.push(memoryMessage); | ||
| } | ||
| // TODO: we still might have too many tokens | ||
| // e.g. too large system messages or transient messages | ||
| // how should we deal with that? | ||
| return this.calcCurrentRequestMessages(); | ||
| } | ||
| return requestMessages; | ||
| } | ||
| async getAllMessages() { | ||
| return this.getMessages(); | ||
| } | ||
| put(message) { | ||
| this.messages.push(message); | ||
| } | ||
| } | ||
| export { BaseMemory, ChatMemoryBuffer, ChatSummaryMemoryBuffer }; |
| Object.defineProperty(exports, '__esModule', { value: true }); | ||
| class BaseChatStore { | ||
| } | ||
| class SimpleChatStore extends BaseChatStore { | ||
| #store; | ||
| setMessages(key, messages) { | ||
| this.#store.set(key, messages); | ||
| } | ||
| getMessages(key) { | ||
| return this.#store.get(key) ?? []; | ||
| } | ||
| addMessage(key, message, idx) { | ||
| const messages = this.#store.get(key) ?? []; | ||
| if (idx === undefined) { | ||
| messages.push(message); | ||
| } else { | ||
| messages.splice(idx, 0, message); | ||
| } | ||
| this.#store.set(key, messages); | ||
| } | ||
| deleteMessages(key) { | ||
| this.#store.delete(key); | ||
| } | ||
| deleteMessage(key, idx) { | ||
| const messages = this.#store.get(key) ?? []; | ||
| messages.splice(idx, 1); | ||
| this.#store.set(key, messages); | ||
| } | ||
| getKeys() { | ||
| return this.#store.keys(); | ||
| } | ||
| constructor(...args){ | ||
| super(...args); | ||
| this.#store = new Map(); | ||
| } | ||
| } | ||
| exports.BaseChatStore = BaseChatStore; | ||
| exports.SimpleChatStore = SimpleChatStore; |
| import { ChatMessage } from '../../llms/index.cjs'; | ||
| declare abstract class BaseChatStore<AdditionalMessageOptions extends object = object> { | ||
| abstract setMessages(key: string, messages: ChatMessage<AdditionalMessageOptions>[]): void; | ||
| abstract getMessages(key: string): ChatMessage<AdditionalMessageOptions>[]; | ||
| abstract addMessage(key: string, message: ChatMessage<AdditionalMessageOptions>, idx?: number): void; | ||
| abstract deleteMessages(key: string): void; | ||
| abstract deleteMessage(key: string, idx: number): void; | ||
| abstract getKeys(): IterableIterator<string>; | ||
| } | ||
| declare class SimpleChatStore<AdditionalMessageOptions extends object = object> extends BaseChatStore<AdditionalMessageOptions> { | ||
| #private; | ||
| setMessages(key: string, messages: ChatMessage<AdditionalMessageOptions>[]): void; | ||
| getMessages(key: string): ChatMessage<AdditionalMessageOptions>[]; | ||
| addMessage(key: string, message: ChatMessage<AdditionalMessageOptions>, idx?: number): void; | ||
| deleteMessages(key: string): void; | ||
| deleteMessage(key: string, idx: number): void; | ||
| getKeys(): MapIterator<string>; | ||
| } | ||
| export { BaseChatStore, SimpleChatStore }; |
| import { ChatMessage } from '../../llms/index.js'; | ||
| declare abstract class BaseChatStore<AdditionalMessageOptions extends object = object> { | ||
| abstract setMessages(key: string, messages: ChatMessage<AdditionalMessageOptions>[]): void; | ||
| abstract getMessages(key: string): ChatMessage<AdditionalMessageOptions>[]; | ||
| abstract addMessage(key: string, message: ChatMessage<AdditionalMessageOptions>, idx?: number): void; | ||
| abstract deleteMessages(key: string): void; | ||
| abstract deleteMessage(key: string, idx: number): void; | ||
| abstract getKeys(): IterableIterator<string>; | ||
| } | ||
| declare class SimpleChatStore<AdditionalMessageOptions extends object = object> extends BaseChatStore<AdditionalMessageOptions> { | ||
| #private; | ||
| setMessages(key: string, messages: ChatMessage<AdditionalMessageOptions>[]): void; | ||
| getMessages(key: string): ChatMessage<AdditionalMessageOptions>[]; | ||
| addMessage(key: string, message: ChatMessage<AdditionalMessageOptions>, idx?: number): void; | ||
| deleteMessages(key: string): void; | ||
| deleteMessage(key: string, idx: number): void; | ||
| getKeys(): MapIterator<string>; | ||
| } | ||
| export { BaseChatStore, SimpleChatStore }; |
| class BaseChatStore { | ||
| } | ||
| class SimpleChatStore extends BaseChatStore { | ||
| #store; | ||
| setMessages(key, messages) { | ||
| this.#store.set(key, messages); | ||
| } | ||
| getMessages(key) { | ||
| return this.#store.get(key) ?? []; | ||
| } | ||
| addMessage(key, message, idx) { | ||
| const messages = this.#store.get(key) ?? []; | ||
| if (idx === undefined) { | ||
| messages.push(message); | ||
| } else { | ||
| messages.splice(idx, 0, message); | ||
| } | ||
| this.#store.set(key, messages); | ||
| } | ||
| deleteMessages(key) { | ||
| this.#store.delete(key); | ||
| } | ||
| deleteMessage(key, idx) { | ||
| const messages = this.#store.get(key) ?? []; | ||
| messages.splice(idx, 1); | ||
| this.#store.set(key, messages); | ||
| } | ||
| getKeys() { | ||
| return this.#store.keys(); | ||
| } | ||
| constructor(...args){ | ||
| super(...args); | ||
| this.#store = new Map(); | ||
| } | ||
| } | ||
| export { BaseChatStore, SimpleChatStore }; |
@@ -76,23 +76,36 @@ Object.defineProperty(exports, '__esModule', { value: true }); | ||
| class BaseEmbedding extends index_cjs.TransformComponent { | ||
| constructor(){ | ||
| super(async (nodes, options)=>{ | ||
| const texts = nodes.map((node)=>node.getContent(index_cjs.MetadataMode.EMBED)); | ||
| const embeddings = await this.getTextEmbeddingsBatch(texts, options); | ||
| for(let i = 0; i < nodes.length; i++){ | ||
| nodes[i].embedding = embeddings[i]; | ||
| } | ||
| return nodes; | ||
| }); | ||
| this.embedBatchSize = DEFAULT_EMBED_BATCH_SIZE; | ||
| /** | ||
| constructor(transformFn){ | ||
| if (transformFn) { | ||
| super(transformFn); | ||
| this.embedBatchSize = DEFAULT_EMBED_BATCH_SIZE; | ||
| /** | ||
| * Optionally override this method to retrieve multiple embeddings in a single request | ||
| * @param texts | ||
| */ this.getTextEmbeddings = async (texts)=>{ | ||
| const embeddings = []; | ||
| for (const text of texts){ | ||
| const embedding = await this.getTextEmbedding(text); | ||
| embeddings.push(embedding); | ||
| } | ||
| return embeddings; | ||
| }; | ||
| const embeddings = []; | ||
| for (const text of texts){ | ||
| const embedding = await this.getTextEmbedding(text); | ||
| embeddings.push(embedding); | ||
| } | ||
| return embeddings; | ||
| }; | ||
| } else { | ||
| super(async (nodes, options)=>{ | ||
| const texts = nodes.map((node)=>node.getContent(index_cjs.MetadataMode.EMBED)); | ||
| const embeddings = await this.getTextEmbeddingsBatch(texts, options); | ||
| for(let i = 0; i < nodes.length; i++){ | ||
| nodes[i].embedding = embeddings[i]; | ||
| } | ||
| return nodes; | ||
| }); | ||
| this.embedBatchSize = DEFAULT_EMBED_BATCH_SIZE; | ||
| this.getTextEmbeddings = async (texts)=>{ | ||
| const embeddings = []; | ||
| for (const text of texts){ | ||
| const embedding = await this.getTextEmbedding(text); | ||
| embeddings.push(embedding); | ||
| } | ||
| return embeddings; | ||
| }; | ||
| } | ||
| } | ||
@@ -142,6 +155,45 @@ similarity(embedding1, embedding2, mode = exports.SimilarityType.DEFAULT) { | ||
| /* | ||
| * Base class for Multi Modal embeddings. | ||
| */ class MultiModalEmbedding extends BaseEmbedding { | ||
| constructor(){ | ||
| super(async (nodes, options)=>{ | ||
| const nodeMap = index_cjs.splitNodesByType(nodes); | ||
| const imageNodes = nodeMap[index_cjs.ModalityType.IMAGE] ?? []; | ||
| const textNodes = nodeMap[index_cjs.ModalityType.TEXT] ?? []; | ||
| const embeddings = await batchEmbeddings(textNodes.map((node)=>node.getContent(index_cjs.MetadataMode.EMBED)), this.getTextEmbeddings.bind(this), this.embedBatchSize, options); | ||
| for(let i = 0; i < textNodes.length; i++){ | ||
| textNodes[i].embedding = embeddings[i]; | ||
| } | ||
| const imageEmbeddings = await batchEmbeddings(imageNodes.map((n)=>n.image), this.getImageEmbeddings.bind(this), this.embedBatchSize, options); | ||
| for(let i = 0; i < imageNodes.length; i++){ | ||
| imageNodes[i].embedding = imageEmbeddings[i]; | ||
| } | ||
| return nodes; | ||
| }); | ||
| } | ||
| /** | ||
| * Optionally override this method to retrieve multiple image embeddings in a single request | ||
| * @param images | ||
| */ async getImageEmbeddings(images) { | ||
| return Promise.all(images.map((imgFilePath)=>this.getImageEmbedding(imgFilePath))); | ||
| } | ||
| async getQueryEmbedding(query) { | ||
| const image = index_cjs$1.extractImage(query); | ||
| if (image) { | ||
| return await this.getImageEmbedding(image); | ||
| } | ||
| const text = index_cjs$1.extractSingleText(query); | ||
| if (text) { | ||
| return await this.getTextEmbedding(text); | ||
| } | ||
| return null; | ||
| } | ||
| } | ||
| exports.BaseEmbedding = BaseEmbedding; | ||
| exports.DEFAULT_SIMILARITY_TOP_K = DEFAULT_SIMILARITY_TOP_K; | ||
| exports.MultiModalEmbedding = MultiModalEmbedding; | ||
| exports.batchEmbeddings = batchEmbeddings; | ||
| exports.similarity = similarity; | ||
| exports.truncateMaxTokens = truncateMaxTokens; |
| import { Tokenizers } from '@llamaindex/env'; | ||
| import { MessageContentDetail } from '../llms/index.cjs'; | ||
| import { TransformComponent } from '../schema/index.cjs'; | ||
| import { TransformComponent, BaseNode, ImageType } from '../schema/index.cjs'; | ||
@@ -36,3 +36,3 @@ declare const DEFAULT_SIMILARITY_TOP_K = 2; | ||
| embedInfo?: EmbeddingInfo; | ||
| constructor(); | ||
| protected constructor(transformFn?: (nodes: BaseNode[], options?: BaseEmbeddingOptions) => Promise<BaseNode[]>); | ||
| similarity(embedding1: number[], embedding2: number[], mode?: SimilarityType): number; | ||
@@ -56,4 +56,15 @@ abstract getTextEmbedding(text: string): Promise<number[]>; | ||
| declare abstract class MultiModalEmbedding extends BaseEmbedding { | ||
| abstract getImageEmbedding(images: ImageType): Promise<number[]>; | ||
| protected constructor(); | ||
| /** | ||
| * Optionally override this method to retrieve multiple image embeddings in a single request | ||
| * @param images | ||
| */ | ||
| getImageEmbeddings(images: ImageType[]): Promise<number[][]>; | ||
| getQueryEmbedding(query: MessageContentDetail): Promise<number[] | null>; | ||
| } | ||
| declare function truncateMaxTokens(tokenizer: Tokenizers, value: string, maxTokens: number): string; | ||
| export { BaseEmbedding, type BaseEmbeddingOptions, DEFAULT_SIMILARITY_TOP_K, type EmbeddingInfo, SimilarityType, batchEmbeddings, similarity, truncateMaxTokens }; | ||
| export { BaseEmbedding, type BaseEmbeddingOptions, DEFAULT_SIMILARITY_TOP_K, type EmbeddingInfo, MultiModalEmbedding, SimilarityType, batchEmbeddings, similarity, truncateMaxTokens }; |
| import { Tokenizers } from '@llamaindex/env'; | ||
| import { MessageContentDetail } from '../llms/index.js'; | ||
| import { TransformComponent } from '../schema/index.js'; | ||
| import { TransformComponent, BaseNode, ImageType } from '../schema/index.js'; | ||
@@ -36,3 +36,3 @@ declare const DEFAULT_SIMILARITY_TOP_K = 2; | ||
| embedInfo?: EmbeddingInfo; | ||
| constructor(); | ||
| protected constructor(transformFn?: (nodes: BaseNode[], options?: BaseEmbeddingOptions) => Promise<BaseNode[]>); | ||
| similarity(embedding1: number[], embedding2: number[], mode?: SimilarityType): number; | ||
@@ -56,4 +56,15 @@ abstract getTextEmbedding(text: string): Promise<number[]>; | ||
| declare abstract class MultiModalEmbedding extends BaseEmbedding { | ||
| abstract getImageEmbedding(images: ImageType): Promise<number[]>; | ||
| protected constructor(); | ||
| /** | ||
| * Optionally override this method to retrieve multiple image embeddings in a single request | ||
| * @param images | ||
| */ | ||
| getImageEmbeddings(images: ImageType[]): Promise<number[][]>; | ||
| getQueryEmbedding(query: MessageContentDetail): Promise<number[] | null>; | ||
| } | ||
| declare function truncateMaxTokens(tokenizer: Tokenizers, value: string, maxTokens: number): string; | ||
| export { BaseEmbedding, type BaseEmbeddingOptions, DEFAULT_SIMILARITY_TOP_K, type EmbeddingInfo, SimilarityType, batchEmbeddings, similarity, truncateMaxTokens }; | ||
| export { BaseEmbedding, type BaseEmbeddingOptions, DEFAULT_SIMILARITY_TOP_K, type EmbeddingInfo, MultiModalEmbedding, SimilarityType, batchEmbeddings, similarity, truncateMaxTokens }; |
+72
-21
@@ -1,3 +0,3 @@ | ||
| import { TransformComponent, MetadataMode } from '../schema/index.js'; | ||
| import { extractSingleText } from '../utils/index.js'; | ||
| import { TransformComponent, MetadataMode, splitNodesByType, ModalityType } from '../schema/index.js'; | ||
| import { extractSingleText, extractImage } from '../utils/index.js'; | ||
| import { tokenizers } from '@llamaindex/env'; | ||
@@ -74,23 +74,36 @@ | ||
| class BaseEmbedding extends TransformComponent { | ||
| constructor(){ | ||
| super(async (nodes, options)=>{ | ||
| const texts = nodes.map((node)=>node.getContent(MetadataMode.EMBED)); | ||
| const embeddings = await this.getTextEmbeddingsBatch(texts, options); | ||
| for(let i = 0; i < nodes.length; i++){ | ||
| nodes[i].embedding = embeddings[i]; | ||
| } | ||
| return nodes; | ||
| }); | ||
| this.embedBatchSize = DEFAULT_EMBED_BATCH_SIZE; | ||
| /** | ||
| constructor(transformFn){ | ||
| if (transformFn) { | ||
| super(transformFn); | ||
| this.embedBatchSize = DEFAULT_EMBED_BATCH_SIZE; | ||
| /** | ||
| * Optionally override this method to retrieve multiple embeddings in a single request | ||
| * @param texts | ||
| */ this.getTextEmbeddings = async (texts)=>{ | ||
| const embeddings = []; | ||
| for (const text of texts){ | ||
| const embedding = await this.getTextEmbedding(text); | ||
| embeddings.push(embedding); | ||
| } | ||
| return embeddings; | ||
| }; | ||
| const embeddings = []; | ||
| for (const text of texts){ | ||
| const embedding = await this.getTextEmbedding(text); | ||
| embeddings.push(embedding); | ||
| } | ||
| return embeddings; | ||
| }; | ||
| } else { | ||
| super(async (nodes, options)=>{ | ||
| const texts = nodes.map((node)=>node.getContent(MetadataMode.EMBED)); | ||
| const embeddings = await this.getTextEmbeddingsBatch(texts, options); | ||
| for(let i = 0; i < nodes.length; i++){ | ||
| nodes[i].embedding = embeddings[i]; | ||
| } | ||
| return nodes; | ||
| }); | ||
| this.embedBatchSize = DEFAULT_EMBED_BATCH_SIZE; | ||
| this.getTextEmbeddings = async (texts)=>{ | ||
| const embeddings = []; | ||
| for (const text of texts){ | ||
| const embedding = await this.getTextEmbedding(text); | ||
| embeddings.push(embedding); | ||
| } | ||
| return embeddings; | ||
| }; | ||
| } | ||
| } | ||
@@ -140,2 +153,40 @@ similarity(embedding1, embedding2, mode = SimilarityType.DEFAULT) { | ||
| export { BaseEmbedding, DEFAULT_SIMILARITY_TOP_K, SimilarityType, batchEmbeddings, similarity, truncateMaxTokens }; | ||
| /* | ||
| * Base class for Multi Modal embeddings. | ||
| */ class MultiModalEmbedding extends BaseEmbedding { | ||
| constructor(){ | ||
| super(async (nodes, options)=>{ | ||
| const nodeMap = splitNodesByType(nodes); | ||
| const imageNodes = nodeMap[ModalityType.IMAGE] ?? []; | ||
| const textNodes = nodeMap[ModalityType.TEXT] ?? []; | ||
| const embeddings = await batchEmbeddings(textNodes.map((node)=>node.getContent(MetadataMode.EMBED)), this.getTextEmbeddings.bind(this), this.embedBatchSize, options); | ||
| for(let i = 0; i < textNodes.length; i++){ | ||
| textNodes[i].embedding = embeddings[i]; | ||
| } | ||
| const imageEmbeddings = await batchEmbeddings(imageNodes.map((n)=>n.image), this.getImageEmbeddings.bind(this), this.embedBatchSize, options); | ||
| for(let i = 0; i < imageNodes.length; i++){ | ||
| imageNodes[i].embedding = imageEmbeddings[i]; | ||
| } | ||
| return nodes; | ||
| }); | ||
| } | ||
| /** | ||
| * Optionally override this method to retrieve multiple image embeddings in a single request | ||
| * @param images | ||
| */ async getImageEmbeddings(images) { | ||
| return Promise.all(images.map((imgFilePath)=>this.getImageEmbedding(imgFilePath))); | ||
| } | ||
| async getQueryEmbedding(query) { | ||
| const image = extractImage(query); | ||
| if (image) { | ||
| return await this.getImageEmbedding(image); | ||
| } | ||
| const text = extractSingleText(query); | ||
| if (text) { | ||
| return await this.getTextEmbedding(text); | ||
| } | ||
| return null; | ||
| } | ||
| } | ||
| export { BaseEmbedding, DEFAULT_SIMILARITY_TOP_K, MultiModalEmbedding, SimilarityType, batchEmbeddings, similarity, truncateMaxTokens }; |
+29
-1
| { | ||
| "name": "@llamaindex/core", | ||
| "type": "module", | ||
| "version": "0.2.1", | ||
| "version": "0.2.2", | ||
| "description": "LlamaIndex Core Module", | ||
@@ -160,2 +160,30 @@ "exports": { | ||
| } | ||
| }, | ||
| "./memory": { | ||
| "require": { | ||
| "types": "./dist/memory/index.d.cts", | ||
| "default": "./dist/memory/index.cjs" | ||
| }, | ||
| "import": { | ||
| "types": "./dist/memory/index.d.ts", | ||
| "default": "./dist/memory/index.js" | ||
| }, | ||
| "default": { | ||
| "types": "./dist/memory/index.d.ts", | ||
| "default": "./dist/memory/index.js" | ||
| } | ||
| }, | ||
| "./storage/chat-store": { | ||
| "require": { | ||
| "types": "./dist/storage/chat-store/index.d.cts", | ||
| "default": "./dist/storage/chat-store/index.cjs" | ||
| }, | ||
| "import": { | ||
| "types": "./dist/storage/chat-store/index.d.ts", | ||
| "default": "./dist/storage/chat-store/index.js" | ||
| }, | ||
| "default": { | ||
| "types": "./dist/storage/chat-store/index.d.ts", | ||
| "default": "./dist/storage/chat-store/index.js" | ||
| } | ||
| } | ||
@@ -162,0 +190,0 @@ }, |
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
364741
10.25%54
17.39%7945
9.1%