{"version":3,"file":"friendli.cjs","names":["ChatMessage","HumanMessage","AIMessage","SystemMessage","HumanMessageChunk","AIMessageChunk","SystemMessageChunk","ChatMessageChunk","BaseChatModel","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  // oxlint-disable-next-line typescript/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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"}