UNPKG

genkitx-ollama

Version:

Genkit AI framework plugin for Ollama APIs.

1 lines 22.3 kB
{"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"]}