@theia/ai-ollama 1.57.0 → 1.58.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/node/ollama-backend-module.d.ts.map +1 -1
- package/lib/node/ollama-backend-module.js +6 -1
- package/lib/node/ollama-backend-module.js.map +1 -1
- package/lib/node/ollama-language-model.d.ts +35 -5
- package/lib/node/ollama-language-model.d.ts.map +1 -1
- package/lib/node/ollama-language-model.js +107 -31
- package/lib/node/ollama-language-model.js.map +1 -1
- package/package.json +7 -7
- package/src/node/ollama-backend-module.ts +7 -1
- package/src/node/ollama-language-model.ts +134 -36
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ollama-backend-module.d.ts","sourceRoot":"","sources":["../../src/node/ollama-backend-module.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"ollama-backend-module.d.ts","sourceRoot":"","sources":["../../src/node/ollama-backend-module.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAM/D,eAAO,MAAM,kBAAkB,eAA+B,CAAC;;AAW/D,wBAEG"}
|
|
@@ -20,10 +20,15 @@ const inversify_1 = require("@theia/core/shared/inversify");
|
|
|
20
20
|
const ollama_language_models_manager_1 = require("../common/ollama-language-models-manager");
|
|
21
21
|
const core_1 = require("@theia/core");
|
|
22
22
|
const ollama_language_models_manager_impl_1 = require("./ollama-language-models-manager-impl");
|
|
23
|
+
const connection_container_module_1 = require("@theia/core/lib/node/messaging/connection-container-module");
|
|
23
24
|
exports.OllamaModelFactory = Symbol('OllamaModelFactory');
|
|
24
|
-
|
|
25
|
+
// We use a connection module to handle AI services separately for each frontend.
|
|
26
|
+
const ollamaConnectionModule = connection_container_module_1.ConnectionContainerModule.create(({ bind, bindBackendService, bindFrontendService }) => {
|
|
25
27
|
bind(ollama_language_models_manager_impl_1.OllamaLanguageModelsManagerImpl).toSelf().inSingletonScope();
|
|
26
28
|
bind(ollama_language_models_manager_1.OllamaLanguageModelsManager).toService(ollama_language_models_manager_impl_1.OllamaLanguageModelsManagerImpl);
|
|
27
29
|
bind(core_1.ConnectionHandler).toDynamicValue(ctx => new core_1.RpcConnectionHandler(ollama_language_models_manager_1.OLLAMA_LANGUAGE_MODELS_MANAGER_PATH, () => ctx.container.get(ollama_language_models_manager_1.OllamaLanguageModelsManager))).inSingletonScope();
|
|
28
30
|
});
|
|
31
|
+
exports.default = new inversify_1.ContainerModule(bind => {
|
|
32
|
+
bind(connection_container_module_1.ConnectionContainerModule).toConstantValue(ollamaConnectionModule);
|
|
33
|
+
});
|
|
29
34
|
//# sourceMappingURL=ollama-backend-module.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ollama-backend-module.js","sourceRoot":"","sources":["../../src/node/ollama-backend-module.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,mCAAmC;AACnC,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;;;AAEhF,4DAA+D;AAC/D,6FAA4H;AAC5H,sCAAsE;AACtE,+FAAwF;
|
|
1
|
+
{"version":3,"file":"ollama-backend-module.js","sourceRoot":"","sources":["../../src/node/ollama-backend-module.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,mCAAmC;AACnC,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;;;AAEhF,4DAA+D;AAC/D,6FAA4H;AAC5H,sCAAsE;AACtE,+FAAwF;AACxF,4GAAuG;AAE1F,QAAA,kBAAkB,GAAG,MAAM,CAAC,oBAAoB,CAAC,CAAC;AAE/D,iFAAiF;AACjF,MAAM,sBAAsB,GAAG,uDAAyB,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,EAAE,EAAE;IAClH,IAAI,CAAC,qEAA+B,CAAC,CAAC,MAAM,EAAE,CAAC,gBAAgB,EAAE,CAAC;IAClE,IAAI,CAAC,4DAA2B,CAAC,CAAC,SAAS,CAAC,qEAA+B,CAAC,CAAC;IAC7E,IAAI,CAAC,wBAAiB,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CACzC,IAAI,2BAAoB,CAAC,oEAAmC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,4DAA2B,CAAC,CAAC,CACtH,CAAC,gBAAgB,EAAE,CAAC;AACzB,CAAC,CAAC,CAAC;AAEH,kBAAe,IAAI,2BAAe,CAAC,IAAI,CAAC,EAAE;IACtC,IAAI,CAAC,uDAAyB,CAAC,CAAC,eAAe,CAAC,sBAAsB,CAAC,CAAC;AAC5E,CAAC,CAAC,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { LanguageModel, LanguageModelParsedResponse, LanguageModelRequest, LanguageModelRequestMessage, LanguageModelResponse, ToolRequest } from '@theia/ai-core';
|
|
1
|
+
import { LanguageModel, LanguageModelParsedResponse, LanguageModelRequest, LanguageModelRequestMessage, LanguageModelResponse, LanguageModelStreamResponse, ToolRequest } from '@theia/ai-core';
|
|
2
2
|
import { CancellationToken } from '@theia/core';
|
|
3
|
-
import { ChatRequest, Message, Ollama, Tool } from 'ollama';
|
|
3
|
+
import { ChatRequest, ChatResponse, Message, Ollama, Tool } from 'ollama';
|
|
4
4
|
export declare const OllamaModelIdentifier: unique symbol;
|
|
5
5
|
export declare class OllamaModel implements LanguageModel {
|
|
6
6
|
readonly id: string;
|
|
@@ -21,11 +21,41 @@ export declare class OllamaModel implements LanguageModel {
|
|
|
21
21
|
constructor(id: string, model: string, host: () => string | undefined, defaultRequestSettings?: {
|
|
22
22
|
[key: string]: unknown;
|
|
23
23
|
} | undefined);
|
|
24
|
-
protected getSettings(request: LanguageModelRequest): Partial<ChatRequest>;
|
|
25
24
|
request(request: LanguageModelRequest, cancellationToken?: CancellationToken): Promise<LanguageModelResponse>;
|
|
26
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Retrieves the settings for the chat request, merging the request-specific settings with the default settings.
|
|
27
|
+
* @param request The language model request containing specific settings.
|
|
28
|
+
* @returns A partial ChatRequest object containing the merged settings.
|
|
29
|
+
*/
|
|
30
|
+
protected getSettings(request: LanguageModelRequest): Partial<ChatRequest>;
|
|
31
|
+
protected dispatchRequest(ollama: Ollama, ollamaRequest: ExtendedChatRequest, structured: boolean, cancellation?: CancellationToken): Promise<LanguageModelResponse>;
|
|
32
|
+
protected handleToolsRequest(ollama: Ollama, chatRequest: ExtendedChatRequest, prevResponse?: ChatResponse): Promise<LanguageModelResponse>;
|
|
33
|
+
protected createAsyncIterable<T>(items: T[]): AsyncIterable<T>;
|
|
34
|
+
protected handleStructuredOutputRequest(ollama: Ollama, chatRequest: ChatRequest): Promise<LanguageModelParsedResponse>;
|
|
27
35
|
protected initializeOllama(): Ollama;
|
|
28
|
-
protected
|
|
36
|
+
protected handleCancellationAndWrapIterator(response: AbortableAsyncIterable<ChatResponse>, token?: CancellationToken): LanguageModelStreamResponse;
|
|
37
|
+
protected toOllamaTool(tool: ToolRequest): ToolWithHandler;
|
|
29
38
|
protected toOllamaMessage(message: LanguageModelRequestMessage): Message;
|
|
30
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Extended Tool containing a handler
|
|
42
|
+
* @see Tool
|
|
43
|
+
*/
|
|
44
|
+
type ToolWithHandler = Tool & {
|
|
45
|
+
handler: (arg_string: string) => Promise<unknown>;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Extended chat request with mandatory messages and ToolWithHandler tools
|
|
49
|
+
*
|
|
50
|
+
* @see ChatRequest
|
|
51
|
+
* @see ToolWithHandler
|
|
52
|
+
*/
|
|
53
|
+
type ExtendedChatRequest = ChatRequest & {
|
|
54
|
+
messages: Message[];
|
|
55
|
+
tools?: ToolWithHandler[];
|
|
56
|
+
};
|
|
57
|
+
type AbortableAsyncIterable<T> = AsyncIterable<T> & {
|
|
58
|
+
abort: () => void;
|
|
59
|
+
};
|
|
60
|
+
export {};
|
|
31
61
|
//# sourceMappingURL=ollama-language-model.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ollama-language-model.d.ts","sourceRoot":"","sources":["../../src/node/ollama-language-model.ts"],"names":[],"mappings":"AAgBA,OAAO,EACH,aAAa,EACb,2BAA2B,EAC3B,oBAAoB,EACpB,2BAA2B,EAC3B,qBAAqB,
|
|
1
|
+
{"version":3,"file":"ollama-language-model.d.ts","sourceRoot":"","sources":["../../src/node/ollama-language-model.ts"],"names":[],"mappings":"AAgBA,OAAO,EACH,aAAa,EACb,2BAA2B,EAC3B,oBAAoB,EACpB,2BAA2B,EAC3B,qBAAqB,EACrB,2BAA2B,EAG3B,WAAW,EACd,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAW,IAAI,EAAE,MAAM,QAAQ,CAAC;AAEnF,eAAO,MAAM,qBAAqB,eAAkC,CAAC;AAErE,qBAAa,WAAY,YAAW,aAAa;aAkBzB,EAAE,EAAE,MAAM;IAC1B,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM;IAChC,SAAS,CAAC,IAAI,EAAE,MAAM,MAAM,GAAG,SAAS;IACjC,sBAAsB,CAAC;;;IAnBlC,SAAS,CAAC,QAAQ,CAAC,wBAAwB,EAAE,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,GAAG,OAAO,CAAC,CAAC,CAIzF;IAEF,QAAQ,CAAC,UAAU,YAAY;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAY;IAEnC;;;;;OAKG;gBAEiB,EAAE,EAAE,MAAM,EACP,KAAK,EAAE,MAAM,EACtB,IAAI,EAAE,MAAM,MAAM,GAAG,SAAS,EACjC,sBAAsB,CAAC;;iBAA4B;IAGxD,OAAO,CAAC,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAenH;;;;OAIG;IACH,SAAS,CAAC,WAAW,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,WAAW,CAAC;cAO1D,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,mBAAmB,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,qBAAqB,CAAC;cAoB1J,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,mBAAmB,EAAE,YAAY,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,qBAAqB,CAAC;IA8CjJ,SAAS,CAAC,mBAAmB,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,aAAa,CAAC,CAAC,CAAC;cAU9C,6BAA6B,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,2BAA2B,CAAC;IAqB7H,SAAS,CAAC,gBAAgB,IAAI,MAAM;IAQpC,SAAS,CAAC,iCAAiC,CAAC,QAAQ,EAAE,sBAAsB,CAAC,YAAY,CAAC,EAAE,KAAK,CAAC,EAAE,iBAAiB,GAAG,2BAA2B;IAanJ,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE,WAAW,GAAG,eAAe;IA+B1D,SAAS,CAAC,eAAe,CAAC,OAAO,EAAE,2BAA2B,GAAG,OAAO;CAY3E;AAED;;;GAGG;AACH,KAAK,eAAe,GAAG,IAAI,GAAG;IAAE,OAAO,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CAAE,CAAC;AAEpF;;;;;GAKG;AACH,KAAK,mBAAmB,GAAG,WAAW,GAAG;IACrC,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,KAAK,CAAC,EAAE,eAAe,EAAE,CAAA;CAC5B,CAAC;AAGF,KAAK,sBAAsB,CAAC,CAAC,IAAI,aAAa,CAAC,CAAC,CAAC,GAAG;IAAE,KAAK,EAAE,MAAM,IAAI,CAAA;CAAE,CAAC"}
|
|
@@ -31,11 +31,32 @@ class OllamaModel {
|
|
|
31
31
|
this.host = host;
|
|
32
32
|
this.defaultRequestSettings = defaultRequestSettings;
|
|
33
33
|
this.DEFAULT_REQUEST_SETTINGS = {
|
|
34
|
-
keep_alive: '15m'
|
|
34
|
+
keep_alive: '15m',
|
|
35
|
+
// options see: https://github.com/ollama/ollama/blob/main/docs/modelfile.md#valid-parameters-and-values
|
|
36
|
+
options: {}
|
|
35
37
|
};
|
|
36
38
|
this.providerId = 'ollama';
|
|
37
39
|
this.vendor = 'Ollama';
|
|
38
40
|
}
|
|
41
|
+
async request(request, cancellationToken) {
|
|
42
|
+
var _a, _b;
|
|
43
|
+
const settings = this.getSettings(request);
|
|
44
|
+
const ollama = this.initializeOllama();
|
|
45
|
+
const ollamaRequest = {
|
|
46
|
+
model: this.model,
|
|
47
|
+
...this.DEFAULT_REQUEST_SETTINGS,
|
|
48
|
+
...settings,
|
|
49
|
+
messages: request.messages.map(this.toOllamaMessage),
|
|
50
|
+
tools: (_a = request.tools) === null || _a === void 0 ? void 0 : _a.map(this.toOllamaTool)
|
|
51
|
+
};
|
|
52
|
+
const structured = ((_b = request.response_format) === null || _b === void 0 ? void 0 : _b.type) === 'json_schema';
|
|
53
|
+
return this.dispatchRequest(ollama, ollamaRequest, structured, cancellationToken);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Retrieves the settings for the chat request, merging the request-specific settings with the default settings.
|
|
57
|
+
* @param request The language model request containing specific settings.
|
|
58
|
+
* @returns A partial ChatRequest object containing the merged settings.
|
|
59
|
+
*/
|
|
39
60
|
getSettings(request) {
|
|
40
61
|
var _a, _b;
|
|
41
62
|
const settings = (_b = (_a = request.settings) !== null && _a !== void 0 ? _a : this.defaultRequestSettings) !== null && _b !== void 0 ? _b : {};
|
|
@@ -43,53 +64,95 @@ class OllamaModel {
|
|
|
43
64
|
options: settings
|
|
44
65
|
};
|
|
45
66
|
}
|
|
46
|
-
async
|
|
47
|
-
var _a
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
return this.handleStructuredOutputRequest(ollama, request);
|
|
67
|
+
async dispatchRequest(ollama, ollamaRequest, structured, cancellation) {
|
|
68
|
+
var _a;
|
|
69
|
+
// Handle structured output request
|
|
70
|
+
if (structured) {
|
|
71
|
+
return this.handleStructuredOutputRequest(ollama, ollamaRequest);
|
|
52
72
|
}
|
|
73
|
+
// Handle tool request - response may call tools
|
|
74
|
+
if (ollamaRequest.tools && ((_a = ollamaRequest.tools) === null || _a === void 0 ? void 0 : _a.length) > 0) {
|
|
75
|
+
return this.handleToolsRequest(ollama, ollamaRequest);
|
|
76
|
+
}
|
|
77
|
+
// Handle standard chat request
|
|
53
78
|
const response = await ollama.chat({
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
...settings,
|
|
57
|
-
messages: request.messages.map(this.toOllamaMessage),
|
|
58
|
-
stream: true,
|
|
59
|
-
tools: (_b = request.tools) === null || _b === void 0 ? void 0 : _b.map(this.toOllamaTool),
|
|
79
|
+
...ollamaRequest,
|
|
80
|
+
stream: true
|
|
60
81
|
});
|
|
61
|
-
|
|
62
|
-
|
|
82
|
+
return this.handleCancellationAndWrapIterator(response, cancellation);
|
|
83
|
+
}
|
|
84
|
+
async handleToolsRequest(ollama, chatRequest, prevResponse) {
|
|
85
|
+
var _a, _b, _c, _d;
|
|
86
|
+
const response = prevResponse || await ollama.chat({
|
|
87
|
+
...chatRequest,
|
|
88
|
+
stream: false
|
|
63
89
|
});
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
90
|
+
if (response.message.tool_calls) {
|
|
91
|
+
const tools = (_a = chatRequest.tools) !== null && _a !== void 0 ? _a : [];
|
|
92
|
+
// Add response message to chat history
|
|
93
|
+
chatRequest.messages.push(response.message);
|
|
94
|
+
const tool_calls = [];
|
|
95
|
+
for (const [idx, toolCall] of response.message.tool_calls.entries()) {
|
|
96
|
+
const functionToCall = tools.find(tool => tool.function.name === toolCall.function.name);
|
|
97
|
+
if (functionToCall) {
|
|
98
|
+
const args = JSON.stringify((_b = toolCall.function) === null || _b === void 0 ? void 0 : _b.arguments);
|
|
99
|
+
const funcResult = await functionToCall.handler(args);
|
|
100
|
+
chatRequest.messages.push({
|
|
101
|
+
role: 'tool',
|
|
102
|
+
content: `Tool call ${functionToCall.function.name} returned: ${String(funcResult)}`,
|
|
103
|
+
});
|
|
104
|
+
let resultString = String(funcResult);
|
|
105
|
+
if (resultString.length > 1000) {
|
|
106
|
+
// truncate result string if it is too long
|
|
107
|
+
resultString = resultString.substring(0, 1000) + '...';
|
|
108
|
+
}
|
|
109
|
+
tool_calls.push({
|
|
110
|
+
id: `ollama_${response.created_at}_${idx}`,
|
|
111
|
+
function: {
|
|
112
|
+
name: functionToCall.function.name,
|
|
113
|
+
arguments: Object.values((_d = (_c = toolCall.function) === null || _c === void 0 ? void 0 : _c.arguments) !== null && _d !== void 0 ? _d : {}).join(', ')
|
|
114
|
+
},
|
|
115
|
+
result: resultString,
|
|
116
|
+
finished: true
|
|
117
|
+
});
|
|
118
|
+
}
|
|
68
119
|
}
|
|
120
|
+
// Get final response from model with function outputs
|
|
121
|
+
const finalResponse = await ollama.chat({ ...chatRequest, stream: false });
|
|
122
|
+
if (finalResponse.message.tool_calls) {
|
|
123
|
+
// If the final response also calls tools, recursively handle them
|
|
124
|
+
return this.handleToolsRequest(ollama, chatRequest, finalResponse);
|
|
125
|
+
}
|
|
126
|
+
return { stream: this.createAsyncIterable([{ tool_calls }, { content: finalResponse.message.content }]) };
|
|
69
127
|
}
|
|
70
|
-
return {
|
|
128
|
+
return { text: response.message.content };
|
|
71
129
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
130
|
+
createAsyncIterable(items) {
|
|
131
|
+
return {
|
|
132
|
+
[Symbol.asyncIterator]: async function* () {
|
|
133
|
+
for (const item of items) {
|
|
134
|
+
yield item;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
async handleStructuredOutputRequest(ollama, chatRequest) {
|
|
140
|
+
const response = await ollama.chat({
|
|
141
|
+
...chatRequest,
|
|
79
142
|
format: 'json',
|
|
80
143
|
stream: false,
|
|
81
144
|
});
|
|
82
145
|
try {
|
|
83
146
|
return {
|
|
84
|
-
content:
|
|
85
|
-
parsed: JSON.parse(
|
|
147
|
+
content: response.message.content,
|
|
148
|
+
parsed: JSON.parse(response.message.content)
|
|
86
149
|
};
|
|
87
150
|
}
|
|
88
151
|
catch (error) {
|
|
89
152
|
// TODO use ILogger
|
|
90
153
|
console.log('Failed to parse structured response from the language model.', error);
|
|
91
154
|
return {
|
|
92
|
-
content:
|
|
155
|
+
content: response.message.content,
|
|
93
156
|
parsed: {}
|
|
94
157
|
};
|
|
95
158
|
}
|
|
@@ -101,6 +164,18 @@ class OllamaModel {
|
|
|
101
164
|
}
|
|
102
165
|
return new ollama_1.Ollama({ host: host });
|
|
103
166
|
}
|
|
167
|
+
handleCancellationAndWrapIterator(response, token) {
|
|
168
|
+
token === null || token === void 0 ? void 0 : token.onCancellationRequested(() => {
|
|
169
|
+
// maybe it is better to use ollama.abort() as we are using one client per request
|
|
170
|
+
response.abort();
|
|
171
|
+
});
|
|
172
|
+
async function* wrapAsyncIterator(inputIterable) {
|
|
173
|
+
for await (const item of inputIterable) {
|
|
174
|
+
yield { content: item.message.content };
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return { stream: wrapAsyncIterator(response) };
|
|
178
|
+
}
|
|
104
179
|
toOllamaTool(tool) {
|
|
105
180
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
106
181
|
const transform = (props) => {
|
|
@@ -128,7 +203,8 @@ class OllamaModel {
|
|
|
128
203
|
required: Object.keys((_e = (_d = tool.parameters) === null || _d === void 0 ? void 0 : _d.properties) !== null && _e !== void 0 ? _e : {}),
|
|
129
204
|
properties: (_g = transform((_f = tool.parameters) === null || _f === void 0 ? void 0 : _f.properties)) !== null && _g !== void 0 ? _g : {}
|
|
130
205
|
},
|
|
131
|
-
}
|
|
206
|
+
},
|
|
207
|
+
handler: tool.handler
|
|
132
208
|
};
|
|
133
209
|
}
|
|
134
210
|
toOllamaMessage(message) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ollama-language-model.js","sourceRoot":"","sources":["../../src/node/ollama-language-model.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,mCAAmC;AACnC,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;;;
|
|
1
|
+
{"version":3,"file":"ollama-language-model.js","sourceRoot":"","sources":["../../src/node/ollama-language-model.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theia/ai-ollama",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.58.0",
|
|
4
4
|
"description": "Theia - Ollama Integration",
|
|
5
5
|
"dependencies": {
|
|
6
|
-
"@theia/ai-core": "1.
|
|
7
|
-
"@theia/core": "1.
|
|
8
|
-
"@theia/filesystem": "1.
|
|
9
|
-
"@theia/workspace": "1.
|
|
6
|
+
"@theia/ai-core": "1.58.0",
|
|
7
|
+
"@theia/core": "1.58.0",
|
|
8
|
+
"@theia/filesystem": "1.58.0",
|
|
9
|
+
"@theia/workspace": "1.58.0",
|
|
10
10
|
"minimatch": "^5.1.0",
|
|
11
11
|
"ollama": "^0.5.8",
|
|
12
12
|
"tslib": "^2.6.2"
|
|
@@ -45,10 +45,10 @@
|
|
|
45
45
|
"watch": "theiaext watch"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@theia/ext-scripts": "1.
|
|
48
|
+
"@theia/ext-scripts": "1.58.0"
|
|
49
49
|
},
|
|
50
50
|
"nyc": {
|
|
51
51
|
"extends": "../../configs/nyc.json"
|
|
52
52
|
},
|
|
53
|
-
"gitHead": "
|
|
53
|
+
"gitHead": "6594f32b9727aea20d88934bf386dee06d08fa5e"
|
|
54
54
|
}
|
|
@@ -18,13 +18,19 @@ import { ContainerModule } from '@theia/core/shared/inversify';
|
|
|
18
18
|
import { OLLAMA_LANGUAGE_MODELS_MANAGER_PATH, OllamaLanguageModelsManager } from '../common/ollama-language-models-manager';
|
|
19
19
|
import { ConnectionHandler, RpcConnectionHandler } from '@theia/core';
|
|
20
20
|
import { OllamaLanguageModelsManagerImpl } from './ollama-language-models-manager-impl';
|
|
21
|
+
import { ConnectionContainerModule } from '@theia/core/lib/node/messaging/connection-container-module';
|
|
21
22
|
|
|
22
23
|
export const OllamaModelFactory = Symbol('OllamaModelFactory');
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
// We use a connection module to handle AI services separately for each frontend.
|
|
26
|
+
const ollamaConnectionModule = ConnectionContainerModule.create(({ bind, bindBackendService, bindFrontendService }) => {
|
|
25
27
|
bind(OllamaLanguageModelsManagerImpl).toSelf().inSingletonScope();
|
|
26
28
|
bind(OllamaLanguageModelsManager).toService(OllamaLanguageModelsManagerImpl);
|
|
27
29
|
bind(ConnectionHandler).toDynamicValue(ctx =>
|
|
28
30
|
new RpcConnectionHandler(OLLAMA_LANGUAGE_MODELS_MANAGER_PATH, () => ctx.container.get(OllamaLanguageModelsManager))
|
|
29
31
|
).inSingletonScope();
|
|
30
32
|
});
|
|
33
|
+
|
|
34
|
+
export default new ContainerModule(bind => {
|
|
35
|
+
bind(ConnectionContainerModule).toConstantValue(ollamaConnectionModule);
|
|
36
|
+
});
|
|
@@ -20,7 +20,9 @@ import {
|
|
|
20
20
|
LanguageModelRequest,
|
|
21
21
|
LanguageModelRequestMessage,
|
|
22
22
|
LanguageModelResponse,
|
|
23
|
+
LanguageModelStreamResponse,
|
|
23
24
|
LanguageModelStreamResponsePart,
|
|
25
|
+
ToolCall,
|
|
24
26
|
ToolRequest
|
|
25
27
|
} from '@theia/ai-core';
|
|
26
28
|
import { CancellationToken } from '@theia/core';
|
|
@@ -31,7 +33,9 @@ export const OllamaModelIdentifier = Symbol('OllamaModelIdentifier');
|
|
|
31
33
|
export class OllamaModel implements LanguageModel {
|
|
32
34
|
|
|
33
35
|
protected readonly DEFAULT_REQUEST_SETTINGS: Partial<Omit<ChatRequest, 'stream' | 'model'>> = {
|
|
34
|
-
keep_alive: '15m'
|
|
36
|
+
keep_alive: '15m',
|
|
37
|
+
// options see: https://github.com/ollama/ollama/blob/main/docs/modelfile.md#valid-parameters-and-values
|
|
38
|
+
options: {}
|
|
35
39
|
};
|
|
36
40
|
|
|
37
41
|
readonly providerId = 'ollama';
|
|
@@ -50,6 +54,26 @@ export class OllamaModel implements LanguageModel {
|
|
|
50
54
|
public defaultRequestSettings?: { [key: string]: unknown }
|
|
51
55
|
) { }
|
|
52
56
|
|
|
57
|
+
async request(request: LanguageModelRequest, cancellationToken?: CancellationToken): Promise<LanguageModelResponse> {
|
|
58
|
+
const settings = this.getSettings(request);
|
|
59
|
+
const ollama = this.initializeOllama();
|
|
60
|
+
|
|
61
|
+
const ollamaRequest: ExtendedChatRequest = {
|
|
62
|
+
model: this.model,
|
|
63
|
+
...this.DEFAULT_REQUEST_SETTINGS,
|
|
64
|
+
...settings,
|
|
65
|
+
messages: request.messages.map(this.toOllamaMessage),
|
|
66
|
+
tools: request.tools?.map(this.toOllamaTool)
|
|
67
|
+
};
|
|
68
|
+
const structured = request.response_format?.type === 'json_schema';
|
|
69
|
+
return this.dispatchRequest(ollama, ollamaRequest, structured, cancellationToken);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Retrieves the settings for the chat request, merging the request-specific settings with the default settings.
|
|
74
|
+
* @param request The language model request containing specific settings.
|
|
75
|
+
* @returns A partial ChatRequest object containing the merged settings.
|
|
76
|
+
*/
|
|
53
77
|
protected getSettings(request: LanguageModelRequest): Partial<ChatRequest> {
|
|
54
78
|
const settings = request.settings ?? this.defaultRequestSettings ?? {};
|
|
55
79
|
return {
|
|
@@ -57,55 +81,98 @@ export class OllamaModel implements LanguageModel {
|
|
|
57
81
|
};
|
|
58
82
|
}
|
|
59
83
|
|
|
60
|
-
async
|
|
61
|
-
|
|
62
|
-
|
|
84
|
+
protected async dispatchRequest(ollama: Ollama, ollamaRequest: ExtendedChatRequest, structured: boolean, cancellation?: CancellationToken): Promise<LanguageModelResponse> {
|
|
85
|
+
|
|
86
|
+
// Handle structured output request
|
|
87
|
+
if (structured) {
|
|
88
|
+
return this.handleStructuredOutputRequest(ollama, ollamaRequest);
|
|
89
|
+
}
|
|
63
90
|
|
|
64
|
-
|
|
65
|
-
|
|
91
|
+
// Handle tool request - response may call tools
|
|
92
|
+
if (ollamaRequest.tools && ollamaRequest.tools?.length > 0) {
|
|
93
|
+
return this.handleToolsRequest(ollama, ollamaRequest);
|
|
66
94
|
}
|
|
95
|
+
|
|
96
|
+
// Handle standard chat request
|
|
67
97
|
const response = await ollama.chat({
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
...settings,
|
|
71
|
-
messages: request.messages.map(this.toOllamaMessage),
|
|
72
|
-
stream: true,
|
|
73
|
-
tools: request.tools?.map(this.toOllamaTool),
|
|
98
|
+
...ollamaRequest,
|
|
99
|
+
stream: true
|
|
74
100
|
});
|
|
101
|
+
return this.handleCancellationAndWrapIterator(response, cancellation);
|
|
102
|
+
}
|
|
75
103
|
|
|
76
|
-
|
|
77
|
-
|
|
104
|
+
protected async handleToolsRequest(ollama: Ollama, chatRequest: ExtendedChatRequest, prevResponse?: ChatResponse): Promise<LanguageModelResponse> {
|
|
105
|
+
const response = prevResponse || await ollama.chat({
|
|
106
|
+
...chatRequest,
|
|
107
|
+
stream: false
|
|
78
108
|
});
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
109
|
+
if (response.message.tool_calls) {
|
|
110
|
+
const tools: ToolWithHandler[] = chatRequest.tools ?? [];
|
|
111
|
+
// Add response message to chat history
|
|
112
|
+
chatRequest.messages.push(response.message);
|
|
113
|
+
const tool_calls: ToolCall[] = [];
|
|
114
|
+
for (const [idx, toolCall] of response.message.tool_calls.entries()) {
|
|
115
|
+
const functionToCall = tools.find(tool => tool.function.name === toolCall.function.name);
|
|
116
|
+
if (functionToCall) {
|
|
117
|
+
const args = JSON.stringify(toolCall.function?.arguments);
|
|
118
|
+
const funcResult = await functionToCall.handler(args);
|
|
119
|
+
chatRequest.messages.push({
|
|
120
|
+
role: 'tool',
|
|
121
|
+
content: `Tool call ${functionToCall.function.name} returned: ${String(funcResult)}`,
|
|
122
|
+
});
|
|
123
|
+
let resultString = String(funcResult);
|
|
124
|
+
if (resultString.length > 1000) {
|
|
125
|
+
// truncate result string if it is too long
|
|
126
|
+
resultString = resultString.substring(0, 1000) + '...';
|
|
127
|
+
}
|
|
128
|
+
tool_calls.push({
|
|
129
|
+
id: `ollama_${response.created_at}_${idx}`,
|
|
130
|
+
function: {
|
|
131
|
+
name: functionToCall.function.name,
|
|
132
|
+
arguments: Object.values(toolCall.function?.arguments ?? {}).join(', ')
|
|
133
|
+
},
|
|
134
|
+
result: resultString,
|
|
135
|
+
finished: true
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// Get final response from model with function outputs
|
|
140
|
+
const finalResponse = await ollama.chat({ ...chatRequest, stream: false });
|
|
141
|
+
if (finalResponse.message.tool_calls) {
|
|
142
|
+
// If the final response also calls tools, recursively handle them
|
|
143
|
+
return this.handleToolsRequest(ollama, chatRequest, finalResponse);
|
|
84
144
|
}
|
|
145
|
+
return { stream: this.createAsyncIterable([{ tool_calls }, { content: finalResponse.message.content }]) };
|
|
85
146
|
}
|
|
86
|
-
return {
|
|
147
|
+
return { text: response.message.content };
|
|
87
148
|
}
|
|
88
149
|
|
|
89
|
-
protected
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
150
|
+
protected createAsyncIterable<T>(items: T[]): AsyncIterable<T> {
|
|
151
|
+
return {
|
|
152
|
+
[Symbol.asyncIterator]: async function* (): AsyncIterableIterator<T> {
|
|
153
|
+
for (const item of items) {
|
|
154
|
+
yield item;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
protected async handleStructuredOutputRequest(ollama: Ollama, chatRequest: ChatRequest): Promise<LanguageModelParsedResponse> {
|
|
161
|
+
const response = await ollama.chat({
|
|
162
|
+
...chatRequest,
|
|
96
163
|
format: 'json',
|
|
97
164
|
stream: false,
|
|
98
165
|
});
|
|
99
166
|
try {
|
|
100
167
|
return {
|
|
101
|
-
content:
|
|
102
|
-
parsed: JSON.parse(
|
|
168
|
+
content: response.message.content,
|
|
169
|
+
parsed: JSON.parse(response.message.content)
|
|
103
170
|
};
|
|
104
171
|
} catch (error) {
|
|
105
172
|
// TODO use ILogger
|
|
106
173
|
console.log('Failed to parse structured response from the language model.', error);
|
|
107
174
|
return {
|
|
108
|
-
content:
|
|
175
|
+
content: response.message.content,
|
|
109
176
|
parsed: {}
|
|
110
177
|
};
|
|
111
178
|
}
|
|
@@ -119,11 +186,21 @@ export class OllamaModel implements LanguageModel {
|
|
|
119
186
|
return new Ollama({ host: host });
|
|
120
187
|
}
|
|
121
188
|
|
|
122
|
-
protected
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}
|
|
189
|
+
protected handleCancellationAndWrapIterator(response: AbortableAsyncIterable<ChatResponse>, token?: CancellationToken): LanguageModelStreamResponse {
|
|
190
|
+
token?.onCancellationRequested(() => {
|
|
191
|
+
// maybe it is better to use ollama.abort() as we are using one client per request
|
|
192
|
+
response.abort();
|
|
193
|
+
});
|
|
194
|
+
async function* wrapAsyncIterator<T>(inputIterable: AsyncIterable<ChatResponse>): AsyncIterable<LanguageModelStreamResponsePart> {
|
|
195
|
+
for await (const item of inputIterable) {
|
|
196
|
+
yield { content: item.message.content };
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return { stream: wrapAsyncIterator(response) };
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
protected toOllamaTool(tool: ToolRequest): ToolWithHandler {
|
|
203
|
+
const transform = (props: Record<string, { [key: string]: unknown; type: string; }> | undefined) => {
|
|
127
204
|
if (!props) {
|
|
128
205
|
return undefined;
|
|
129
206
|
}
|
|
@@ -148,7 +225,8 @@ export class OllamaModel implements LanguageModel {
|
|
|
148
225
|
required: Object.keys(tool.parameters?.properties ?? {}),
|
|
149
226
|
properties: transform(tool.parameters?.properties) ?? {}
|
|
150
227
|
},
|
|
151
|
-
}
|
|
228
|
+
},
|
|
229
|
+
handler: tool.handler
|
|
152
230
|
};
|
|
153
231
|
}
|
|
154
232
|
|
|
@@ -165,3 +243,23 @@ export class OllamaModel implements LanguageModel {
|
|
|
165
243
|
return { role: 'system', content: '' };
|
|
166
244
|
}
|
|
167
245
|
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Extended Tool containing a handler
|
|
249
|
+
* @see Tool
|
|
250
|
+
*/
|
|
251
|
+
type ToolWithHandler = Tool & { handler: (arg_string: string) => Promise<unknown> };
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Extended chat request with mandatory messages and ToolWithHandler tools
|
|
255
|
+
*
|
|
256
|
+
* @see ChatRequest
|
|
257
|
+
* @see ToolWithHandler
|
|
258
|
+
*/
|
|
259
|
+
type ExtendedChatRequest = ChatRequest & {
|
|
260
|
+
messages: Message[]
|
|
261
|
+
tools?: ToolWithHandler[]
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
// Ollama doesn't export this type, so we have to define it here
|
|
265
|
+
type AbortableAsyncIterable<T> = AsyncIterable<T> & { abort: () => void };
|