UNPKG

@langchain/community

Version:
1 lines • 16 kB
{"version":3,"file":"llama_cpp.cjs","names":["SimpleChatModel","inputs: LlamaCppInputs","inputs: LlamaBaseCppInputs","createLlamaModel","createLlamaContext","messages: BaseMessage[]","options: this[\"ParsedCallOptions\"]","runManager?: CallbackManagerForLLMRun","tokens: number[]","input: BaseMessage[]","_options: this[\"ParsedCallOptions\"]","ChatGenerationChunk","AIMessageChunk","noSystemMessages: BaseMessage[]","interactions: ChatHistoryItem[]","LlamaChatSession","result: ChatHistoryItem[]","llamaPrompt: ChatUserMessage","llamaResponse: ChatModelResponse","ChatMessage"],"sources":["../../src/chat_models/llama_cpp.ts"],"sourcesContent":["import {\n LlamaModel,\n LlamaContext,\n LlamaChatSession,\n type Token,\n ChatUserMessage,\n ChatModelResponse,\n ChatHistoryItem,\n getLlama,\n} from \"node-llama-cpp\";\n\nimport {\n SimpleChatModel,\n type BaseChatModelParams,\n} from \"@langchain/core/language_models/chat_models\";\nimport type { BaseLanguageModelCallOptions } from \"@langchain/core/language_models/base\";\nimport { CallbackManagerForLLMRun } from \"@langchain/core/callbacks/manager\";\nimport {\n BaseMessage,\n AIMessageChunk,\n ChatMessage,\n} from \"@langchain/core/messages\";\nimport { ChatGenerationChunk } from \"@langchain/core/outputs\";\nimport {\n LlamaBaseCppInputs,\n createLlamaModel,\n createLlamaContext,\n} from \"../utils/llama_cpp.js\";\n\n/**\n * Note that the modelPath is the only required parameter. For testing you\n * can set this in the environment variable `LLAMA_PATH`.\n */\nexport interface LlamaCppInputs\n extends LlamaBaseCppInputs,\n BaseChatModelParams {}\n\nexport interface LlamaCppCallOptions extends BaseLanguageModelCallOptions {\n /** The maximum number of tokens the response should contain. */\n maxTokens?: number;\n /** A function called when matching the provided token array */\n onToken?: (tokens: number[]) => void;\n}\n\n/**\n * To use this model you need to have the `node-llama-cpp` module installed.\n * This can be installed using `npm install -S node-llama-cpp` and the minimum\n * version supported in version 2.0.0.\n * This also requires that have a locally built version of Llama3 installed.\n * @example\n * ```typescript\n * // Initialize the ChatLlamaCpp model with the path to the model binary file.\n * const model = await ChatLlamaCpp.initialize({\n * modelPath: \"/Replace/with/path/to/your/model/gguf-llama3-Q4_0.bin\",\n * temperature: 0.5,\n * });\n *\n * // Call the model with a message and await the response.\n * const response = await model.invoke([\n * new HumanMessage({ content: \"My name is John.\" }),\n * ]);\n *\n * // Log the response to the console.\n * console.log({ response });\n *\n * ```\n */\nexport class ChatLlamaCpp extends SimpleChatModel<LlamaCppCallOptions> {\n static inputs: LlamaCppInputs;\n\n maxTokens?: number;\n\n temperature?: number;\n\n topK?: number;\n\n topP?: number;\n\n trimWhitespaceSuffix?: boolean;\n\n _model: LlamaModel;\n\n _context: LlamaContext;\n\n _session: LlamaChatSession | null;\n\n lc_serializable = true;\n\n static lc_name() {\n return \"ChatLlamaCpp\";\n }\n\n public constructor(inputs: LlamaCppInputs) {\n super(inputs);\n this.maxTokens = inputs?.maxTokens;\n this.temperature = inputs?.temperature;\n this.topK = inputs?.topK;\n this.topP = inputs?.topP;\n this.trimWhitespaceSuffix = inputs?.trimWhitespaceSuffix;\n this._session = null;\n }\n\n /**\n * Initializes the llama_cpp model for usage in the chat models wrapper.\n * @param inputs - the inputs passed onto the model.\n * @returns A Promise that resolves to the ChatLlamaCpp type class.\n */\n public static async initialize(\n inputs: LlamaBaseCppInputs\n ): Promise<ChatLlamaCpp> {\n const instance = new ChatLlamaCpp(inputs);\n const llama = await getLlama();\n\n instance._model = await createLlamaModel(inputs, llama);\n instance._context = await createLlamaContext(instance._model, inputs);\n\n return instance;\n }\n\n _llmType() {\n return \"llama_cpp\";\n }\n\n /** @ignore */\n _combineLLMOutput() {\n return {};\n }\n\n invocationParams() {\n return {\n maxTokens: this.maxTokens,\n temperature: this.temperature,\n topK: this.topK,\n topP: this.topP,\n trimWhitespaceSuffix: this.trimWhitespaceSuffix,\n };\n }\n\n /** @ignore */\n async _call(\n messages: BaseMessage[],\n options: this[\"ParsedCallOptions\"],\n runManager?: CallbackManagerForLLMRun\n ): Promise<string> {\n let prompt = \"\";\n\n if (messages.length > 1) {\n // We need to build a new _session\n prompt = this._buildSession(messages);\n } else if (!this._session) {\n prompt = this._buildSession(messages);\n } else {\n if (typeof messages[0].content !== \"string\") {\n throw new Error(\n \"ChatLlamaCpp does not support non-string message content in sessions.\"\n );\n }\n // If we already have a session then we should just have a single prompt\n prompt = messages[0].content;\n }\n\n try {\n const promptOptions = {\n signal: options.signal,\n onToken: async (tokens: number[]) => {\n options.onToken?.(tokens);\n await runManager?.handleLLMNewToken(\n this._model.detokenize(tokens.map((num) => num as Token))\n );\n },\n maxTokens: this?.maxTokens,\n temperature: this?.temperature,\n topK: this?.topK,\n topP: this?.topP,\n trimWhitespaceSuffix: this?.trimWhitespaceSuffix,\n };\n // @ts-expect-error - TS2531: Object is possibly 'null'.\n const completion = await this._session.prompt(prompt, promptOptions);\n return completion;\n } catch (e) {\n if (typeof e === \"object\") {\n const error = e as Error;\n if (error.message === \"AbortError\") {\n throw error;\n }\n }\n throw new Error(\"Error getting prompt completion.\");\n }\n }\n\n async *_streamResponseChunks(\n input: BaseMessage[],\n _options: this[\"ParsedCallOptions\"],\n runManager?: CallbackManagerForLLMRun\n ): AsyncGenerator<ChatGenerationChunk> {\n const promptOptions = {\n temperature: this?.temperature,\n topK: this?.topK,\n topP: this?.topP,\n };\n\n const prompt = this._buildPrompt(input);\n const sequence = this._context.getSequence();\n\n const stream = await this.caller.call(async () =>\n sequence.evaluate(this._model.tokenize(prompt), promptOptions)\n );\n\n for await (const chunk of stream) {\n yield new ChatGenerationChunk({\n text: this._model.detokenize([chunk]),\n message: new AIMessageChunk({\n content: this._model.detokenize([chunk]),\n }),\n generationInfo: {},\n });\n await runManager?.handleLLMNewToken(\n this._model.detokenize([chunk]) ?? \"\"\n );\n }\n }\n\n // This constructs a new session if we need to adding in any sys messages or previous chats\n protected _buildSession(messages: BaseMessage[]): string {\n let prompt = \"\";\n let sysMessage = \"\";\n let noSystemMessages: BaseMessage[] = [];\n let interactions: ChatHistoryItem[] = [];\n\n // Let's see if we have a system message\n if (messages.findIndex((msg) => msg.getType() === \"system\") !== -1) {\n const sysMessages = messages.filter(\n (message) => message.getType() === \"system\"\n );\n\n const systemMessageContent = sysMessages[sysMessages.length - 1].content;\n\n if (typeof systemMessageContent !== \"string\") {\n throw new Error(\n \"ChatLlamaCpp does not support non-string message content in sessions.\"\n );\n }\n // Only use the last provided system message\n sysMessage = systemMessageContent;\n\n // Now filter out the system messages\n noSystemMessages = messages.filter(\n (message) => message.getType() !== \"system\"\n );\n } else {\n noSystemMessages = messages;\n }\n\n // Lets see if we just have a prompt left or are their previous interactions?\n if (noSystemMessages.length > 1) {\n // Is the last message a prompt?\n if (noSystemMessages[noSystemMessages.length - 1].getType() === \"human\") {\n const finalMessageContent =\n noSystemMessages[noSystemMessages.length - 1].content;\n if (typeof finalMessageContent !== \"string\") {\n throw new Error(\n \"ChatLlamaCpp does not support non-string message content in sessions.\"\n );\n }\n prompt = finalMessageContent;\n interactions = this._convertMessagesToInteractions(\n noSystemMessages.slice(0, noSystemMessages.length - 1)\n );\n } else {\n interactions = this._convertMessagesToInteractions(noSystemMessages);\n }\n } else {\n if (typeof noSystemMessages[0].content !== \"string\") {\n throw new Error(\n \"ChatLlamaCpp does not support non-string message content in sessions.\"\n );\n }\n // If there was only a single message we assume it's a prompt\n prompt = noSystemMessages[0].content;\n }\n\n // Now lets construct a session according to what we got\n if (sysMessage !== \"\" && interactions.length > 0) {\n this._session = new LlamaChatSession({\n contextSequence: this._context.getSequence(),\n systemPrompt: sysMessage,\n });\n this._session.setChatHistory(interactions);\n } else if (sysMessage !== \"\" && interactions.length === 0) {\n this._session = new LlamaChatSession({\n contextSequence: this._context.getSequence(),\n systemPrompt: sysMessage,\n });\n } else if (sysMessage === \"\" && interactions.length > 0) {\n this._session = new LlamaChatSession({\n contextSequence: this._context.getSequence(),\n });\n this._session.setChatHistory(interactions);\n } else {\n this._session = new LlamaChatSession({\n contextSequence: this._context.getSequence(),\n });\n }\n\n return prompt;\n }\n\n // This builds a an array of interactions\n protected _convertMessagesToInteractions(\n messages: BaseMessage[]\n ): ChatHistoryItem[] {\n const result: ChatHistoryItem[] = [];\n\n for (let i = 0; i < messages.length; i += 2) {\n if (i + 1 < messages.length) {\n const prompt = messages[i].content;\n const response = messages[i + 1].content;\n if (typeof prompt !== \"string\" || typeof response !== \"string\") {\n throw new Error(\n \"ChatLlamaCpp does not support non-string message content.\"\n );\n }\n const llamaPrompt: ChatUserMessage = { type: \"user\", text: prompt };\n const llamaResponse: ChatModelResponse = {\n type: \"model\",\n response: [response],\n };\n result.push(llamaPrompt);\n result.push(llamaResponse);\n }\n }\n\n return result;\n }\n\n protected _buildPrompt(input: BaseMessage[]): string {\n const prompt = input\n .map((message) => {\n let messageText;\n if (message.getType() === \"human\") {\n messageText = `[INST] ${message.content} [/INST]`;\n } else if (message.getType() === \"ai\") {\n messageText = message.content;\n } else if (message.getType() === \"system\") {\n messageText = `<<SYS>> ${message.content} <</SYS>>`;\n } else if (ChatMessage.isInstance(message)) {\n messageText = `\\n\\n${message.role[0].toUpperCase()}${message.role.slice(\n 1\n )}: ${message.content}`;\n } else {\n console.warn(\n `Unsupported message type passed to llama_cpp: \"${message.getType()}\"`\n );\n messageText = \"\";\n }\n return messageText;\n })\n .join(\"\\n\");\n\n return prompt;\n }\n}\n"],"mappings":"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"}