{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n  embedderRef,\n  modelActionMetadata,\n  z,\n  type ActionMetadata,\n  type EmbedderReference,\n  type Genkit,\n  type ModelReference,\n  type ToolRequest,\n  type ToolRequestPart,\n  type ToolResponse,\n} from 'genkit';\nimport { logger } from 'genkit/logging';\nimport {\n  GenerationCommonConfigDescriptions,\n  GenerationCommonConfigSchema,\n  getBasicUsageStats,\n  modelRef,\n  type GenerateRequest,\n  type GenerateResponseData,\n  type MessageData,\n  type ModelInfo,\n  type ToolDefinition,\n} from 'genkit/model';\nimport { genkitPlugin, type GenkitPlugin } from 'genkit/plugin';\nimport type { ActionType } from 'genkit/registry';\nimport { defineOllamaEmbedder } from './embeddings.js';\nimport type {\n  ApiType,\n  ListLocalModelsResponse,\n  LocalModel,\n  Message,\n  ModelDefinition,\n  OllamaPluginParams,\n  OllamaTool,\n  OllamaToolCall,\n  RequestHeaders,\n} from './types.js';\n\nexport type { OllamaPluginParams };\n\nexport type OllamaPlugin = {\n  (params?: OllamaPluginParams): GenkitPlugin;\n\n  model(\n    name: string,\n    config?: z.infer<typeof OllamaConfigSchema>\n  ): ModelReference<typeof OllamaConfigSchema>;\n  embedder(name: string, config?: Record<string, any>): EmbedderReference;\n};\n\nconst ANY_JSON_SCHEMA: Record<string, any> = {\n  $schema: 'http://json-schema.org/draft-07/schema#',\n};\n\nconst GENERIC_MODEL_INFO = {\n  supports: {\n    multiturn: true,\n    media: true,\n    tools: true,\n    toolChoice: true,\n    systemRole: true,\n    constrained: 'all',\n  },\n} as ModelInfo;\n\nconst DEFAULT_OLLAMA_SERVER_ADDRESS = 'http://localhost:11434';\n\nasync function initializer(\n  ai: Genkit,\n  serverAddress: string,\n  params?: OllamaPluginParams\n) {\n  params?.models?.map((model) =>\n    defineOllamaModel(ai, model, serverAddress, params?.requestHeaders)\n  );\n  params?.embedders?.map((model) =>\n    defineOllamaEmbedder(ai, {\n      name: model.name,\n      modelName: model.name,\n      dimensions: model.dimensions,\n      options: params!,\n    })\n  );\n}\n\nfunction resolveAction(\n  ai: Genkit,\n  actionType: ActionType,\n  actionName: string,\n  serverAddress: string,\n  requestHeaders?: RequestHeaders\n) {\n  // We can only dynamically resolve models, for embedders user must provide dimensions.\n  if (actionType === 'model') {\n    defineOllamaModel(\n      ai,\n      {\n        name: actionName,\n      },\n      serverAddress,\n      requestHeaders\n    );\n  }\n}\n\nasync function listActions(\n  serverAddress: string,\n  requestHeaders?: RequestHeaders\n): Promise<ActionMetadata[]> {\n  const models = await listLocalModels(serverAddress, requestHeaders);\n  return (\n    models\n      // naively filter out embedders, unfortunately there's no better way.\n      ?.filter((m) => m.model && !m.model.includes('embed'))\n      .map((m) =>\n        modelActionMetadata({\n          name: `ollama/${m.model}`,\n          info: GENERIC_MODEL_INFO,\n        })\n      ) || []\n  );\n}\n\nfunction ollamaPlugin(params?: OllamaPluginParams): GenkitPlugin {\n  if (!params) {\n    params = {};\n  }\n  if (!params.serverAddress) {\n    params.serverAddress = DEFAULT_OLLAMA_SERVER_ADDRESS;\n  }\n  const serverAddress = params.serverAddress;\n  return genkitPlugin(\n    'ollama',\n    async (ai: Genkit) => {\n      await initializer(ai, serverAddress, params);\n    },\n    async (ai, actionType, actionName) => {\n      resolveAction(\n        ai,\n        actionType,\n        actionName,\n        serverAddress,\n        params?.requestHeaders\n      );\n    },\n    async () => await listActions(serverAddress, params?.requestHeaders)\n  );\n}\n\nasync function listLocalModels(\n  serverAddress: string,\n  requestHeaders?: RequestHeaders\n): Promise<LocalModel[]> {\n  // We call the ollama list local models api: https://github.com/ollama/ollama/blob/main/docs/api.md#list-local-models\n  let res;\n  try {\n    res = await fetch(serverAddress + '/api/tags', {\n      method: 'GET',\n      headers: {\n        'Content-Type': 'application/json',\n        ...(await getHeaders(serverAddress, requestHeaders)),\n      },\n    });\n  } catch (e) {\n    throw new Error(`Make sure the Ollama server is running.`, {\n      cause: e,\n    });\n  }\n  const modelResponse = JSON.parse(await res.text()) as ListLocalModelsResponse;\n  return modelResponse.models;\n}\n\n/**\n * Please refer to: https://github.com/ollama/ollama/blob/main/docs/modelfile.md\n * for further information.\n */\nexport const OllamaConfigSchema = GenerationCommonConfigSchema.extend({\n  temperature: z\n    .number()\n    .min(0.0)\n    .max(1.0)\n    .describe(\n      GenerationCommonConfigDescriptions.temperature +\n        ' The default value is 0.8.'\n    )\n    .optional(),\n  topK: z\n    .number()\n    .describe(\n      GenerationCommonConfigDescriptions.topK + ' The default value is 40.'\n    )\n    .optional(),\n  topP: z\n    .number()\n    .min(0)\n    .max(1.0)\n    .describe(\n      GenerationCommonConfigDescriptions.topP + ' The default value is 0.9.'\n    )\n    .optional(),\n});\n\nfunction defineOllamaModel(\n  ai: Genkit,\n  model: ModelDefinition,\n  serverAddress: string,\n  requestHeaders?: RequestHeaders\n) {\n  return ai.defineModel(\n    {\n      name: `ollama/${model.name}`,\n      label: `Ollama - ${model.name}`,\n      configSchema: OllamaConfigSchema,\n      supports: {\n        multiturn: !model.type || model.type === 'chat',\n        systemRole: true,\n        tools: model.supports?.tools,\n      },\n    },\n    async (input, streamingCallback) => {\n      const { topP, topK, stopSequences, maxOutputTokens, ...rest } =\n        input.config as any;\n      const options: Record<string, any> = { ...rest };\n      if (topP !== undefined) {\n        options.top_p = topP;\n      }\n      if (topK !== undefined) {\n        options.top_k = topK;\n      }\n      if (stopSequences !== undefined) {\n        options.stop = stopSequences.join('');\n      }\n      if (maxOutputTokens !== undefined) {\n        options.num_predict = maxOutputTokens;\n      }\n      const type = model.type ?? 'chat';\n      const request = toOllamaRequest(\n        model.name,\n        input,\n        options,\n        type,\n        !!streamingCallback\n      );\n      logger.debug(request, `ollama request (${type})`);\n\n      const extraHeaders = await getHeaders(\n        serverAddress,\n        requestHeaders,\n        model,\n        input\n      );\n      let res;\n      try {\n        res = await fetch(\n          serverAddress + (type === 'chat' ? '/api/chat' : '/api/generate'),\n          {\n            method: 'POST',\n            body: JSON.stringify(request),\n            headers: {\n              'Content-Type': 'application/json',\n              ...extraHeaders,\n            },\n          }\n        );\n      } catch (e) {\n        const cause = (e as any).cause;\n        if (\n          cause &&\n          cause instanceof Error &&\n          cause.message?.includes('ECONNREFUSED')\n        ) {\n          cause.message += '. Make sure the Ollama server is running.';\n          throw cause;\n        }\n        throw e;\n      }\n      if (!res.body) {\n        throw new Error('Response has no body');\n      }\n\n      let message: MessageData;\n\n      if (streamingCallback) {\n        const reader = res.body.getReader();\n        const textDecoder = new TextDecoder();\n        let textResponse = '';\n        for await (const chunk of readChunks(reader)) {\n          const chunkText = textDecoder.decode(chunk);\n          const json = JSON.parse(chunkText);\n          const message = parseMessage(json, type);\n          streamingCallback({\n            index: 0,\n            content: message.content,\n          });\n          textResponse += message.content[0].text;\n        }\n        message = {\n          role: 'model',\n          content: [\n            {\n              text: textResponse,\n            },\n          ],\n        };\n      } else {\n        const txtBody = await res.text();\n        const json = JSON.parse(txtBody);\n        logger.debug(txtBody, 'ollama raw response');\n\n        message = parseMessage(json, type);\n      }\n\n      return {\n        message,\n        usage: getBasicUsageStats(input.messages, message),\n        finishReason: 'stop',\n      } as GenerateResponseData;\n    }\n  );\n}\n\nfunction parseMessage(response: any, type: ApiType): MessageData {\n  if (response.error) {\n    throw new Error(response.error);\n  }\n  if (type === 'chat') {\n    // Tool calling is available only on the 'chat' API, not on 'generate'\n    // https://github.com/ollama/ollama/blob/main/docs/api.md#chat-request-with-tools\n    if (response.message.tool_calls && response.message.tool_calls.length > 0) {\n      return {\n        role: toGenkitRole(response.message.role),\n        content: toGenkitToolRequest(response.message.tool_calls),\n      };\n    } else {\n      return {\n        role: toGenkitRole(response.message.role),\n        content: [\n          {\n            text: response.message.content,\n          },\n        ],\n      };\n    }\n  } else {\n    return {\n      role: 'model',\n      content: [\n        {\n          text: response.response,\n        },\n      ],\n    };\n  }\n}\n\nasync function getHeaders(\n  serverAddress: string,\n  requestHeaders?: RequestHeaders,\n  model?: ModelDefinition,\n  input?: GenerateRequest\n): Promise<Record<string, string> | void> {\n  return requestHeaders\n    ? typeof requestHeaders === 'function'\n      ? await requestHeaders(\n          {\n            serverAddress,\n            model,\n          },\n          input\n        )\n      : requestHeaders\n    : {};\n}\n\nfunction toOllamaRequest(\n  name: string,\n  input: GenerateRequest,\n  options: Record<string, any>,\n  type: ApiType,\n  stream: boolean\n) {\n  const request: any = {\n    model: name,\n    options,\n    stream,\n    tools: input.tools?.filter(isValidOllamaTool).map(toOllamaTool),\n  };\n  if (type === 'chat') {\n    const messages: Message[] = [];\n    input.messages.forEach((m) => {\n      let messageText = '';\n      const role = toOllamaRole(m.role);\n      const images: string[] = [];\n      const toolRequests: ToolRequest[] = [];\n      const toolResponses: ToolResponse[] = [];\n      m.content.forEach((c) => {\n        if (c.text) {\n          messageText += c.text;\n        }\n        if (c.media) {\n          let imageUri = c.media.url;\n          // ollama doesn't accept full data URIs, just the base64 encoded image,\n          // strip out data URI prefix (ex. `data:image/jpeg;base64,`)\n          if (imageUri.startsWith('data:')) {\n            imageUri = imageUri.substring(imageUri.indexOf(',') + 1);\n          }\n          images.push(imageUri);\n        }\n        if (c.toolRequest) {\n          toolRequests.push(c.toolRequest);\n        }\n        if (c.toolResponse) {\n          toolResponses.push(c.toolResponse);\n        }\n      });\n      // Add tool responses, if any.\n      toolResponses.forEach((t) => {\n        messages.push({\n          role,\n          content:\n            typeof t.output === 'string' ? t.output : JSON.stringify(t.output),\n        });\n      });\n      messages.push({\n        role: role,\n        content: toolRequests.length > 0 ? '' : messageText,\n        images: images.length > 0 ? images : undefined,\n        tool_calls:\n          toolRequests.length > 0 ? toOllamaToolCall(toolRequests) : undefined,\n      });\n    });\n    request.messages = messages;\n  } else {\n    request.prompt = getPrompt(input);\n    request.system = getSystemMessage(input);\n  }\n  return request;\n}\n\nfunction toOllamaRole(role) {\n  if (role === 'model') {\n    return 'assistant';\n  }\n  return role; // everything else seems to match\n}\n\nfunction toGenkitRole(role) {\n  if (role === 'assistant') {\n    return 'model';\n  }\n  return role; // everything else seems to match\n}\n\nfunction toOllamaTool(tool: ToolDefinition): OllamaTool {\n  return {\n    type: 'function',\n    function: {\n      name: tool.name,\n      description: tool.description,\n      parameters: tool.inputSchema ?? ANY_JSON_SCHEMA,\n    },\n  };\n}\n\nfunction toOllamaToolCall(toolRequests: ToolRequest[]): OllamaToolCall[] {\n  return toolRequests.map((t) => ({\n    function: {\n      name: t.name,\n      // This should be safe since we already filtered tools that don't accept\n      // objects\n      arguments: t.input as Record<string, any>,\n    },\n  }));\n}\n\nfunction toGenkitToolRequest(tool_calls: OllamaToolCall[]): ToolRequestPart[] {\n  return tool_calls.map((t) => ({\n    toolRequest: {\n      name: t.function.name,\n      ref: t.function.index ? t.function.index.toString() : undefined,\n      input: t.function.arguments,\n    },\n  }));\n}\n\nfunction readChunks(reader) {\n  return {\n    async *[Symbol.asyncIterator]() {\n      let readResult = await reader.read();\n      while (!readResult.done) {\n        yield readResult.value;\n        readResult = await reader.read();\n      }\n    },\n  };\n}\n\nfunction getPrompt(input: GenerateRequest): string {\n  return input.messages\n    .filter((m) => m.role !== 'system')\n    .map((m) => m.content.map((c) => c.text).join())\n    .join();\n}\n\nfunction getSystemMessage(input: GenerateRequest): string {\n  return input.messages\n    .filter((m) => m.role === 'system')\n    .map((m) => m.content.map((c) => c.text).join())\n    .join();\n}\n\nfunction isValidOllamaTool(tool: ToolDefinition): boolean {\n  if (tool.inputSchema?.type !== 'object') {\n    throw new Error(\n      `Unsupported tool: '${tool.name}'. Ollama only supports tools with object inputs`\n    );\n  }\n  return true;\n}\n\nexport const ollama = ollamaPlugin as OllamaPlugin;\nollama.model = (\n  name: string,\n  config?: z.infer<typeof OllamaConfigSchema>\n): ModelReference<typeof OllamaConfigSchema> => {\n  return modelRef({\n    name: `ollama/${name}`,\n    config,\n    configSchema: OllamaConfigSchema,\n  });\n};\nollama.embedder = (\n  name: string,\n  config?: Record<string, any>\n): EmbedderReference => {\n  return embedderRef({\n    name: `ollama/${name}`,\n    config,\n  });\n};\n"],"mappings":"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","names":["message"]}