@mandujs/core 0.45.1 → 0.46.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.
@@ -1,235 +0,0 @@
1
- /**
2
- * Brain v0.1 - Ollama LLM Adapter
3
- *
4
- * Default adapter for local sLLM via Ollama.
5
- * Uses official ollama npm package for reliable API integration.
6
- * Recommended models: ministral-3:3b, llama3.2, codellama, mistral
7
- */
8
-
9
- import { Ollama } from "ollama";
10
- import { BaseLLMAdapter } from "./base";
11
- import type {
12
- AdapterConfig,
13
- AdapterStatus,
14
- ChatMessage,
15
- CompletionOptions,
16
- CompletionResult,
17
- } from "../types";
18
-
19
- /**
20
- * Default Ollama configuration
21
- *
22
- * Ministral 3B: 저사양 PC에서도 동작하는 경량 모델
23
- * - 2GB VRAM 이하에서도 CPU 모드로 동작
24
- * - 코드 분석/제안에 충분한 성능
25
- */
26
- export const DEFAULT_OLLAMA_CONFIG: AdapterConfig = {
27
- baseUrl: "http://localhost:11434",
28
- model: "ministral-3:3b", // Mistral's lightweight 3B model (3.0GB)
29
- timeout: 30000, // 30 seconds
30
- };
31
-
32
- /**
33
- * Ollama LLM Adapter
34
- *
35
- * Connects to a local Ollama instance for sLLM inference.
36
- * Falls back gracefully if Ollama is not available.
37
- */
38
- export class OllamaAdapter extends BaseLLMAdapter {
39
- readonly name = "ollama";
40
- private client: Ollama;
41
-
42
- constructor(config: Partial<AdapterConfig> = {}) {
43
- super({
44
- ...DEFAULT_OLLAMA_CONFIG,
45
- ...config,
46
- });
47
-
48
- this.client = new Ollama({
49
- host: this.baseUrl,
50
- });
51
- }
52
-
53
- /**
54
- * Check if Ollama is running and the model is available
55
- */
56
- async checkStatus(): Promise<AdapterStatus> {
57
- try {
58
- const response = await this.client.list();
59
- const models = response.models || [];
60
-
61
- // Check if configured model is available
62
- const modelAvailable = models.some(
63
- (m) =>
64
- m.name === this.config.model ||
65
- m.name.startsWith(`${this.config.model}:`)
66
- );
67
-
68
- if (!modelAvailable) {
69
- // Check if any model is available
70
- if (models.length > 0) {
71
- return {
72
- available: true,
73
- model: models[0].name,
74
- error: `Configured model '${this.config.model}' not found. Using '${models[0].name}' instead.`,
75
- };
76
- }
77
-
78
- return {
79
- available: false,
80
- model: null,
81
- error: `No models available. Run: ollama pull ${this.config.model}`,
82
- };
83
- }
84
-
85
- return {
86
- available: true,
87
- model: this.config.model,
88
- };
89
- } catch (error) {
90
- const errorMessage =
91
- error instanceof Error ? error.message : "Unknown error";
92
-
93
- // Check for common connection errors
94
- if (
95
- errorMessage.includes("ECONNREFUSED") ||
96
- errorMessage.includes("fetch failed") ||
97
- errorMessage.includes("Unable to connect")
98
- ) {
99
- return {
100
- available: false,
101
- model: null,
102
- error: "Ollama is not running. Start with: ollama serve",
103
- };
104
- }
105
-
106
- return {
107
- available: false,
108
- model: null,
109
- error: `Ollama check failed: ${errorMessage}`,
110
- };
111
- }
112
- }
113
-
114
- /**
115
- * Complete a chat conversation using Ollama's chat API
116
- */
117
- async complete(
118
- messages: ChatMessage[],
119
- options: CompletionOptions = {}
120
- ): Promise<CompletionResult> {
121
- const { temperature = 0.7, maxTokens = 2048 } = options;
122
-
123
- try {
124
- const response = await this.client.chat({
125
- model: this.config.model,
126
- messages: messages.map((m) => ({
127
- role: m.role,
128
- content: m.content,
129
- })),
130
- stream: false,
131
- options: {
132
- temperature,
133
- num_predict: maxTokens,
134
- },
135
- });
136
-
137
- return {
138
- content: response.message?.content || "",
139
- usage: {
140
- promptTokens: response.prompt_eval_count || 0,
141
- completionTokens: response.eval_count || 0,
142
- totalTokens:
143
- (response.prompt_eval_count || 0) + (response.eval_count || 0),
144
- },
145
- };
146
- } catch (error) {
147
- if (error instanceof Error && error.name === "AbortError") {
148
- throw new Error("Ollama request timeout", { cause: error });
149
- }
150
- throw error;
151
- }
152
- }
153
-
154
- /**
155
- * Pull a model from Ollama registry with progress callback
156
- */
157
- async pullModel(
158
- modelName?: string,
159
- onProgress?: (status: string, completed?: number, total?: number) => void
160
- ): Promise<{ success: boolean; error?: string }> {
161
- const model = modelName ?? this.config.model;
162
-
163
- try {
164
- const stream = await this.client.pull({
165
- model,
166
- stream: true,
167
- });
168
-
169
- for await (const progress of stream) {
170
- if (onProgress && progress.status) {
171
- onProgress(
172
- progress.status,
173
- progress.completed,
174
- progress.total
175
- );
176
- }
177
- }
178
-
179
- return { success: true };
180
- } catch (error) {
181
- return {
182
- success: false,
183
- error: error instanceof Error ? error.message : "Unknown error",
184
- };
185
- }
186
- }
187
-
188
- /**
189
- * Check if Ollama server is reachable
190
- */
191
- async isServerRunning(): Promise<boolean> {
192
- try {
193
- await this.client.list();
194
- return true;
195
- } catch {
196
- return false;
197
- }
198
- }
199
-
200
- /**
201
- * List all available models
202
- */
203
- async listModels(): Promise<string[]> {
204
- try {
205
- const response = await this.client.list();
206
- return (response.models || []).map((m) => m.name);
207
- } catch {
208
- return [];
209
- }
210
- }
211
-
212
- /**
213
- * Generate embeddings for text
214
- */
215
- async embed(text: string, model?: string): Promise<number[] | null> {
216
- try {
217
- const response = await this.client.embed({
218
- model: model ?? this.config.model,
219
- input: text,
220
- });
221
- return response.embeddings?.[0] ?? null;
222
- } catch {
223
- return null;
224
- }
225
- }
226
- }
227
-
228
- /**
229
- * Create an Ollama adapter with optional configuration
230
- */
231
- export function createOllamaAdapter(
232
- config?: Partial<AdapterConfig>
233
- ): OllamaAdapter {
234
- return new OllamaAdapter(config);
235
- }