@langchain/community
Version:
Third-party integrations for LangChain.js
1 lines • 15.1 kB
Source Map (JSON)
{"version":3,"file":"friendli.cjs","names":["message: BaseMessage","ChatMessage","message: FriendliMessage","HumanMessage","AIMessage","SystemMessage","delta: Record<string, any>","HumanMessageChunk","AIMessageChunk","SystemMessageChunk","ChatMessageChunk","BaseChatModel","fields: ChatFriendliParams","stream: boolean","messages: BaseMessage[]","_options?: this[\"ParsedCallOptions\"]","_options: this[\"ParsedCallOptions\"]","generations: ChatGeneration[]","generation: ChatGeneration","runManager?: CallbackManagerForLLMRun","convertEventStreamToIterableReadableDataStream","ChatGenerationChunk"],"sources":["../../src/chat_models/friendli.ts"],"sourcesContent":["import { CallbackManagerForLLMRun } from \"@langchain/core/callbacks/manager\";\nimport {\n BaseChatModel,\n BaseChatModelCallOptions,\n type BaseChatModelParams,\n} from \"@langchain/core/language_models/chat_models\";\nimport {\n BaseMessage,\n AIMessage,\n ChatMessage,\n HumanMessage,\n SystemMessage,\n HumanMessageChunk,\n AIMessageChunk,\n SystemMessageChunk,\n ChatMessageChunk,\n} from \"@langchain/core/messages\";\nimport {\n ChatGeneration,\n ChatGenerationChunk,\n ChatResult,\n} from \"@langchain/core/outputs\";\nimport { getEnvironmentVariable } from \"@langchain/core/utils/env\";\nimport { convertEventStreamToIterableReadableDataStream } from \"../utils/event_source_parse.js\";\n\n/**\n * Type representing the role of a message in the Friendli chat model.\n */\nexport type FriendliMessageRole = \"system\" | \"assistant\" | \"user\";\n\ninterface FriendliMessage {\n role: FriendliMessageRole;\n content: string;\n}\n\nfunction messageToFriendliRole(message: BaseMessage): FriendliMessageRole {\n const type = message._getType();\n switch (type) {\n case \"ai\":\n return \"assistant\";\n case \"human\":\n return \"user\";\n case \"system\":\n return \"system\";\n case \"function\":\n throw new Error(\"Function messages not supported\");\n case \"generic\": {\n if (!ChatMessage.isInstance(message)) {\n throw new Error(\"Invalid generic chat message\");\n }\n if ([\"system\", \"assistant\", \"user\"].includes(message.role)) {\n return message.role as FriendliMessageRole;\n }\n throw new Error(`Unknown message type: ${type}`);\n }\n default:\n throw new Error(`Unknown message type: ${type}`);\n }\n}\n\nfunction friendliResponseToChatMessage(message: FriendliMessage): BaseMessage {\n switch (message.role) {\n case \"user\":\n return new HumanMessage(message.content ?? \"\");\n case \"assistant\":\n return new AIMessage(message.content ?? \"\");\n case \"system\":\n return new SystemMessage(message.content ?? \"\");\n default:\n return new ChatMessage(message.content ?? \"\", message.role ?? \"unknown\");\n }\n}\n\nfunction _convertDeltaToMessageChunk(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n delta: Record<string, any>\n) {\n const role = delta.role ?? \"assistant\";\n const content = delta.content ?? \"\";\n let additional_kwargs;\n\n if (delta.function_call) {\n additional_kwargs = {\n function_call: delta.function_call,\n };\n } else {\n additional_kwargs = {};\n }\n\n if (role === \"user\") {\n return new HumanMessageChunk({ content });\n } else if (role === \"assistant\") {\n return new AIMessageChunk({ content, additional_kwargs });\n } else if (role === \"system\") {\n return new SystemMessageChunk({ content });\n } else {\n return new ChatMessageChunk({ content, role });\n }\n}\n\n/**\n * The ChatFriendliParams interface defines the input parameters for\n * the ChatFriendli class.\n */\nexport interface ChatFriendliParams extends BaseChatModelParams {\n /**\n * Model name to use.\n */\n model?: string;\n /**\n * Base endpoint url.\n */\n baseUrl?: string;\n /**\n * Friendli personal access token to run as.\n */\n friendliToken?: string;\n /**\n * Friendli team ID to run as.\n */\n friendliTeam?: string;\n /**\n * Number between -2.0 and 2.0. Positive values penalizes tokens that have been\n * sampled, taking into account their frequency in the preceding text. This\n * penalization diminishes the model's tendency to reproduce identical lines\n * verbatim.\n */\n frequencyPenalty?: number;\n /**\n * Number between -2.0 and 2.0. Positive values penalizes tokens that have been\n * sampled at least once in the existing text.\n * presence_penalty: Optional[float] = None\n * The maximum number of tokens to generate. The length of your input tokens plus\n * `max_tokens` should not exceed the model's maximum length (e.g., 2048 for OpenAI\n * GPT-3)\n */\n maxTokens?: number;\n /**\n * When one of the stop phrases appears in the generation result, the API will stop\n * generation. The phrase is included in the generated result. If you are using\n * beam search, all of the active beams should contain the stop phrase to terminate\n * generation. Before checking whether a stop phrase is included in the result, the\n * phrase is converted into tokens.\n */\n stop?: string[];\n /**\n * Sampling temperature. Smaller temperature makes the generation result closer to\n * greedy, argmax (i.e., `top_k = 1`) sampling. If it is `None`, then 1.0 is used.\n */\n temperature?: number;\n /**\n * Tokens comprising the top `top_p` probability mass are kept for sampling. Numbers\n * between 0.0 (exclusive) and 1.0 (inclusive) are allowed. If it is `None`, then 1.0\n * is used by default.\n */\n topP?: number;\n /**\n * Additional kwargs to pass to the model.\n */\n modelKwargs?: Record<string, unknown>;\n}\n\n/**\n * The ChatFriendli class is used to interact with Friendli inference Endpoint models.\n * This requires your Friendli Token and Friendli Team which is autoloaded if not specified.\n */\nexport class ChatFriendli extends BaseChatModel<BaseChatModelCallOptions> {\n lc_serializable = true;\n\n static lc_name() {\n return \"Friendli\";\n }\n\n get lc_secrets(): { [key: string]: string } | undefined {\n return {\n friendliToken: \"FRIENDLI_TOKEN\",\n friendliTeam: \"FRIENDLI_TEAM\",\n };\n }\n\n model = \"meta-llama-3-8b-instruct\";\n\n baseUrl = \"https://inference.friendli.ai\";\n\n friendliToken?: string;\n\n friendliTeam?: string;\n\n frequencyPenalty?: number;\n\n maxTokens?: number;\n\n stop?: string[];\n\n temperature?: number;\n\n topP?: number;\n\n modelKwargs?: Record<string, unknown>;\n\n constructor(fields: ChatFriendliParams) {\n super(fields);\n\n this.model = fields?.model ?? this.model;\n this.baseUrl = fields?.baseUrl ?? this.baseUrl;\n this.friendliToken =\n fields?.friendliToken ?? getEnvironmentVariable(\"FRIENDLI_TOKEN\");\n this.friendliTeam =\n fields?.friendliTeam ?? getEnvironmentVariable(\"FRIENDLI_TEAM\");\n this.frequencyPenalty = fields?.frequencyPenalty ?? this.frequencyPenalty;\n this.maxTokens = fields?.maxTokens ?? this.maxTokens;\n this.stop = fields?.stop ?? this.stop;\n this.temperature = fields?.temperature ?? this.temperature;\n this.topP = fields?.topP ?? this.topP;\n this.modelKwargs = fields?.modelKwargs ?? {};\n\n if (!this.friendliToken) {\n throw new Error(\"Missing Friendli Token\");\n }\n }\n\n _llmType() {\n return \"friendli\";\n }\n\n private constructHeaders(stream: boolean) {\n return {\n \"Content-Type\": \"application/json\",\n Accept: stream ? \"text/event-stream\" : \"application/json\",\n Authorization: `Bearer ${this.friendliToken}`,\n \"X-Friendli-Team\": this.friendliTeam ?? \"\",\n };\n }\n\n private constructBody(\n messages: BaseMessage[],\n stream: boolean,\n _options?: this[\"ParsedCallOptions\"]\n ) {\n const messageList = messages.map((message) => {\n if (typeof message.content !== \"string\") {\n throw new Error(\n \"Friendli does not support non-string message content.\"\n );\n }\n return {\n role: messageToFriendliRole(message),\n content: message.content,\n };\n });\n\n const body = JSON.stringify({\n messages: messageList,\n stream,\n model: this.model,\n max_tokens: this.maxTokens,\n frequency_penalty: this.frequencyPenalty,\n stop: this.stop,\n temperature: this.temperature,\n top_p: this.topP,\n ...this.modelKwargs,\n });\n return body;\n }\n\n /**\n * Calls the Friendli endpoint and retrieves the result.\n * @param {BaseMessage[]} messages The input messages.\n * @returns {Promise<ChatResult>} A promise that resolves to the generated chat result.\n */\n /** @ignore */\n async _generate(\n messages: BaseMessage[],\n _options: this[\"ParsedCallOptions\"]\n ): Promise<ChatResult> {\n interface ChatFriendliResponse {\n choices: {\n index: number;\n message: {\n role: FriendliMessageRole;\n content: string;\n };\n finish_reason: string;\n }[];\n usage: {\n prompt_tokens: number;\n completion_tokens: number;\n total_tokens: number;\n };\n created: number;\n }\n\n const response = (await this.caller.call(async () =>\n fetch(`${this.baseUrl}/v1/chat/completions`, {\n method: \"POST\",\n headers: this.constructHeaders(false),\n body: this.constructBody(messages, false, _options),\n }).then((res) => res.json())\n )) as ChatFriendliResponse;\n\n const generations: ChatGeneration[] = [];\n for (const data of response.choices ?? []) {\n const text = data.message?.content ?? \"\";\n const generation: ChatGeneration = {\n text,\n message: friendliResponseToChatMessage(data.message ?? {}),\n };\n if (data.finish_reason) {\n generation.generationInfo = { finish_reason: data.finish_reason };\n }\n generations.push(generation);\n }\n\n return { generations };\n }\n\n async *_streamResponseChunks(\n messages: BaseMessage[],\n _options: this[\"ParsedCallOptions\"],\n runManager?: CallbackManagerForLLMRun\n ): AsyncGenerator<ChatGenerationChunk> {\n interface ChatFriendliResponse {\n choices: {\n index: number;\n delta: {\n role?: FriendliMessageRole;\n content?: string;\n };\n finish_reason: string | null;\n }[];\n created: number;\n }\n\n const response = await this.caller.call(async () =>\n fetch(`${this.baseUrl}/v1/chat/completions`, {\n method: \"POST\",\n headers: this.constructHeaders(true),\n body: this.constructBody(messages, true, _options),\n })\n );\n\n if (response.status !== 200 || !response.body) {\n const errorResponse = await response.json();\n throw new Error(JSON.stringify(errorResponse));\n }\n\n const stream = convertEventStreamToIterableReadableDataStream(\n response.body\n );\n\n for await (const chunk of stream) {\n if (chunk === \"[DONE]\") break;\n\n const parsedChunk = JSON.parse(chunk) as ChatFriendliResponse;\n\n if (parsedChunk.choices[0].finish_reason === null) {\n const generationChunk = new ChatGenerationChunk({\n message: _convertDeltaToMessageChunk(parsedChunk.choices[0].delta),\n text: parsedChunk.choices[0].delta.content ?? \"\",\n generationInfo: {\n finishReason: parsedChunk.choices[0].finish_reason,\n },\n });\n\n yield generationChunk;\n\n // eslint-disable-next-line no-void\n void runManager?.handleLLMNewToken(generationChunk.text ?? \"\");\n }\n }\n }\n}\n"],"mappings":"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"}