@juspay/neurolink 12.14.9 ā 12.14.11
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/CHANGELOG.md +2 -2
- package/dist/browser/neurolink.min.js +354 -354
- package/dist/cli/commands/config.js +2 -2
- package/dist/cli/commands/setup-huggingface.js +19 -11
- package/dist/core/modelConfiguration.d.ts +3 -3
- package/dist/core/modelConfiguration.js +6 -4
- package/dist/models/manifests/huggingface.d.ts +6 -3
- package/dist/models/manifests/huggingface.js +7 -4
- package/dist/providers/huggingFace/client.d.ts +30 -7
- package/dist/providers/huggingFace/client.js +44 -26
- package/dist/providers/openaiChatCompletionsBase.d.ts +21 -0
- package/dist/providers/openaiChatCompletionsBase.js +307 -7
- package/dist/utils/providerSetupMessages.js +2 -2
- package/docs-site/static/search-index.json +1 -1
- package/package.json +1 -1
|
@@ -87,7 +87,7 @@ const ConfigSchema = z.object({
|
|
|
87
87
|
huggingface: z
|
|
88
88
|
.object({
|
|
89
89
|
apiKey: z.string().optional(),
|
|
90
|
-
model: z.string().default("
|
|
90
|
+
model: z.string().default("Qwen/Qwen2.5-72B-Instruct"),
|
|
91
91
|
})
|
|
92
92
|
.optional(),
|
|
93
93
|
ollama: z
|
|
@@ -783,7 +783,7 @@ export class ConfigManager {
|
|
|
783
783
|
type: "input",
|
|
784
784
|
name: "model",
|
|
785
785
|
message: "Model name:",
|
|
786
|
-
default: "
|
|
786
|
+
default: "Qwen/Qwen2.5-72B-Instruct",
|
|
787
787
|
},
|
|
788
788
|
]);
|
|
789
789
|
this.config.providers.huggingface = answers;
|
|
@@ -92,26 +92,34 @@ export const handleHuggingFaceSetup = async (argv) => {
|
|
|
92
92
|
type: "select",
|
|
93
93
|
name: "modelChoice",
|
|
94
94
|
message: "Select a Hugging Face model:",
|
|
95
|
+
// Router-served ids only. The previous five options
|
|
96
|
+
// (DialoGPT-large/medium/small, blenderbot-400M-distill) are all
|
|
97
|
+
// absent from the router catalogue and answer 400 on every request,
|
|
98
|
+
// so this wizard wrote a dead model into the user's .env.
|
|
95
99
|
choices: [
|
|
96
100
|
{
|
|
97
|
-
name: "Skip - use default (
|
|
101
|
+
name: "Skip - use default (Qwen/Qwen2.5-72B-Instruct)",
|
|
98
102
|
value: "default",
|
|
99
103
|
},
|
|
100
104
|
{
|
|
101
|
-
name: "
|
|
102
|
-
value: "
|
|
105
|
+
name: "Qwen/Qwen2.5-72B-Instruct (Recommended - tool-capable)",
|
|
106
|
+
value: "Qwen/Qwen2.5-72B-Instruct",
|
|
103
107
|
},
|
|
104
108
|
{
|
|
105
|
-
name: "
|
|
106
|
-
value: "
|
|
109
|
+
name: "meta-llama/Llama-3.1-8B-Instruct (Fastest)",
|
|
110
|
+
value: "meta-llama/Llama-3.1-8B-Instruct",
|
|
107
111
|
},
|
|
108
112
|
{
|
|
109
|
-
name: "
|
|
110
|
-
value: "
|
|
113
|
+
name: "meta-llama/Llama-3.3-70B-Instruct (Stronger reasoning)",
|
|
114
|
+
value: "meta-llama/Llama-3.3-70B-Instruct",
|
|
111
115
|
},
|
|
112
116
|
{
|
|
113
|
-
name: "
|
|
114
|
-
value: "
|
|
117
|
+
name: "deepseek-ai/DeepSeek-V3 (Highest quality)",
|
|
118
|
+
value: "deepseek-ai/DeepSeek-V3",
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
name: "Qwen/Qwen2.5-Coder-32B-Instruct (Code-focused)",
|
|
122
|
+
value: "Qwen/Qwen2.5-Coder-32B-Instruct",
|
|
115
123
|
},
|
|
116
124
|
{
|
|
117
125
|
name: "Custom model name",
|
|
@@ -134,7 +142,7 @@ export const handleHuggingFaceSetup = async (argv) => {
|
|
|
134
142
|
return "Model name is required";
|
|
135
143
|
}
|
|
136
144
|
if (!trimmed.includes("/")) {
|
|
137
|
-
return "Model name should include organization (e.g., '
|
|
145
|
+
return "Model name should include organization (e.g., 'Qwen/Qwen2.5-72B-Instruct')";
|
|
138
146
|
}
|
|
139
147
|
return true;
|
|
140
148
|
},
|
|
@@ -173,7 +181,7 @@ export const handleHuggingFaceSetup = async (argv) => {
|
|
|
173
181
|
}
|
|
174
182
|
else {
|
|
175
183
|
logger.always(chalk.gray(' neurolink generate "Tell me a story" --provider huggingface'));
|
|
176
|
-
logger.always(chalk.gray(' neurolink generate "Explain AI" --provider huggingface --model
|
|
184
|
+
logger.always(chalk.gray(' neurolink generate "Explain AI" --provider huggingface --model Qwen/Qwen2.5-72B-Instruct'));
|
|
177
185
|
}
|
|
178
186
|
logger.always(chalk.blue("\nš Resources:"));
|
|
179
187
|
logger.always(chalk.gray(" ⢠Hugging Face Models: https://huggingface.co/models"));
|
|
@@ -51,9 +51,9 @@ export declare const MODEL_NAMES: {
|
|
|
51
51
|
readonly QUALITY: "llama3.1:70b";
|
|
52
52
|
};
|
|
53
53
|
readonly HUGGINGFACE: {
|
|
54
|
-
readonly FAST: "
|
|
55
|
-
readonly BALANCED: "
|
|
56
|
-
readonly QUALITY: "
|
|
54
|
+
readonly FAST: "meta-llama/Llama-3.1-8B-Instruct";
|
|
55
|
+
readonly BALANCED: "Qwen/Qwen2.5-72B-Instruct";
|
|
56
|
+
readonly QUALITY: "deepseek-ai/DeepSeek-V3";
|
|
57
57
|
};
|
|
58
58
|
readonly MISTRAL: {
|
|
59
59
|
readonly FAST: "mistral-small-latest";
|
|
@@ -58,11 +58,13 @@ export const MODEL_NAMES = {
|
|
|
58
58
|
BALANCED: "llama3.1:8b",
|
|
59
59
|
QUALITY: "llama3.1:70b",
|
|
60
60
|
},
|
|
61
|
-
// HuggingFace Models
|
|
61
|
+
// HuggingFace Models ā router-served ids. The previous three
|
|
62
|
+
// (DialoGPT-medium / -large, Llama-2-7b-chat-hf) are absent from the
|
|
63
|
+
// router catalogue and answer 400 on every request.
|
|
62
64
|
HUGGINGFACE: {
|
|
63
|
-
FAST: "
|
|
64
|
-
BALANCED: "
|
|
65
|
-
QUALITY: "
|
|
65
|
+
FAST: "meta-llama/Llama-3.1-8B-Instruct",
|
|
66
|
+
BALANCED: "Qwen/Qwen2.5-72B-Instruct",
|
|
67
|
+
QUALITY: "deepseek-ai/DeepSeek-V3",
|
|
66
68
|
},
|
|
67
69
|
// Mistral Models
|
|
68
70
|
MISTRAL: {
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { ProviderModelManifest } from "../../types/index.js";
|
|
2
2
|
/**
|
|
3
3
|
* Minimal manifest: huggingface has no MODEL_REGISTRY entries today, so
|
|
4
|
-
* only the provider-wide fallback is known.
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* only the provider-wide fallback is known. `functionCalling` is true
|
|
5
|
+
* because the router serves tool-calling models and returns `tool_calls` for
|
|
6
|
+
* them; it previously claimed false, contradicting the wire.
|
|
7
|
+
*
|
|
8
|
+
* Named models can be added here incrementally without touching any
|
|
9
|
+
* consumer ā see Task 5 of the model metadata consolidation plan.
|
|
7
10
|
*/
|
|
8
11
|
export declare const huggingfaceManifest: ProviderModelManifest;
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Minimal manifest: huggingface has no MODEL_REGISTRY entries today, so
|
|
3
|
-
* only the provider-wide fallback is known.
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* only the provider-wide fallback is known. `functionCalling` is true
|
|
4
|
+
* because the router serves tool-calling models and returns `tool_calls` for
|
|
5
|
+
* them; it previously claimed false, contradicting the wire.
|
|
6
|
+
*
|
|
7
|
+
* Named models can be added here incrementally without touching any
|
|
8
|
+
* consumer ā see Task 5 of the model metadata consolidation plan.
|
|
6
9
|
*/
|
|
7
10
|
export const huggingfaceManifest = {
|
|
8
11
|
defaultContextWindow: 32000,
|
|
@@ -12,7 +15,7 @@ export const huggingfaceManifest = {
|
|
|
12
15
|
contextWindow: 32000,
|
|
13
16
|
maxOutputTokens: 32000,
|
|
14
17
|
vision: false,
|
|
15
|
-
functionCalling:
|
|
18
|
+
functionCalling: true,
|
|
16
19
|
},
|
|
17
20
|
},
|
|
18
21
|
};
|
|
@@ -19,13 +19,36 @@ export declare class HuggingFaceProvider extends OpenAIChatCompletionsProvider {
|
|
|
19
19
|
protected getDefaultModel(): string;
|
|
20
20
|
protected getFallbackModelName(): string;
|
|
21
21
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* the
|
|
27
|
-
*
|
|
22
|
+
* Tool support is resolved by the base through MODEL_REGISTRY's
|
|
23
|
+
* `modelSupports()` facade, which defaults unknown models to supported.
|
|
24
|
+
*
|
|
25
|
+
* This class used to override that with a 13-entry allowlist of model-name
|
|
26
|
+
* substrings, written for the old per-model Inference API where many
|
|
27
|
+
* endpoints rejected the OpenAI `tools` field. The router replaced that, and
|
|
28
|
+
* the list did not keep up. Measured against the 142 models
|
|
29
|
+
* `GET router.huggingface.co/v1/models` served on 2026-09-13 (the
|
|
30
|
+
* catalogue drifts, so treat the totals as a snapshot; the ratio is the
|
|
31
|
+
* point):
|
|
32
|
+
*
|
|
33
|
+
* allowlist entries matching ANY served model 1 of 13
|
|
34
|
+
* served models the allowlist ADMITS 1 of 142
|
|
35
|
+
* served models the allowlist BLOCKS 141
|
|
36
|
+
*
|
|
37
|
+
* So it suppressed tool calling for 99% of the catalogue, including
|
|
38
|
+
* Qwen/Qwen2.5-72B-Instruct, which the router demonstrably tool-calls. A
|
|
39
|
+
* spread of the blocked models ā GLM-5.3-Flash, gemma-4-31B-it,
|
|
40
|
+
* DeepSeek-V4-Flash ā all accept `tools` with HTTP 200 and return
|
|
41
|
+
* `tool_calls`; none rejected the field.
|
|
42
|
+
*
|
|
43
|
+
* The allowlist's own comment named `microsoft/DialoGPT-medium` ā which
|
|
44
|
+
* `getDefaultModel()`, not `getFallbackModelName()`, used to return ā as a
|
|
45
|
+
* model that rejects `tools`. The router does not serve it under any
|
|
46
|
+
* request shape, so that path was never reachable; the default now points
|
|
47
|
+
* at a served model (see `getDefaultHuggingFaceModel`).
|
|
48
|
+
*
|
|
49
|
+
* A model that genuinely cannot use tools simply does not emit `tool_calls`,
|
|
50
|
+
* which the loop already handles, so the optimistic default costs nothing
|
|
51
|
+
* that the allowlist was protecting.
|
|
28
52
|
*/
|
|
29
|
-
supportsTools(): boolean;
|
|
30
53
|
protected formatProviderError(error: unknown): Error;
|
|
31
54
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { HuggingFaceModels } from "../../constants/enums.js";
|
|
1
2
|
import { AuthenticationError, InvalidModelError, ProviderError, RateLimitError, } from "../../types/index.js";
|
|
2
3
|
import { classifyProviderError, DEFAULT_ERROR_RULES, } from "../../utils/errorClassifier.js";
|
|
3
4
|
import { logger } from "../../utils/logger.js";
|
|
@@ -6,7 +7,19 @@ import { createHuggingFaceConfig, getProviderModel, validateApiKey, } from "../.
|
|
|
6
7
|
import { OpenAIChatCompletionsProvider } from "../openaiChatCompletionsBase.js";
|
|
7
8
|
const HUGGINGFACE_DEFAULT_BASE_URL = "https://router.huggingface.co/v1";
|
|
8
9
|
const getHuggingFaceApiKey = () => validateApiKey(createHuggingFaceConfig());
|
|
9
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Must stay the same id `providerRegistry` passes as the registration default
|
|
12
|
+
* (`process.env.HUGGINGFACE_MODEL || HuggingFaceModels.QWEN_2_5_72B_INSTRUCT`),
|
|
13
|
+
* hence the shared constant rather than a second literal.
|
|
14
|
+
*
|
|
15
|
+
* The registry supplies `modelName` on every factory-created provider, so this
|
|
16
|
+
* only decides a directly-constructed `new HuggingFaceProvider()`. It still
|
|
17
|
+
* matters: it previously read `microsoft/DialoGPT-medium`, which the router
|
|
18
|
+
* does not serve under any request shape ā it answers 400 "not supported by
|
|
19
|
+
* any provider you have enabled" with or without `tools` ā and that stale id
|
|
20
|
+
* was what the docs and setup guidance advertised as the default.
|
|
21
|
+
*/
|
|
22
|
+
const getDefaultHuggingFaceModel = () => getProviderModel("HUGGINGFACE_MODEL", HuggingFaceModels.QWEN_2_5_72B_INSTRUCT);
|
|
10
23
|
/**
|
|
11
24
|
* HuggingFace Provider ā direct HTTP, no AI SDK.
|
|
12
25
|
*
|
|
@@ -47,32 +60,37 @@ export class HuggingFaceProvider extends OpenAIChatCompletionsProvider {
|
|
|
47
60
|
return "meta-llama/Llama-3.1-8B-Instruct";
|
|
48
61
|
}
|
|
49
62
|
/**
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* the
|
|
55
|
-
*
|
|
63
|
+
* Tool support is resolved by the base through MODEL_REGISTRY's
|
|
64
|
+
* `modelSupports()` facade, which defaults unknown models to supported.
|
|
65
|
+
*
|
|
66
|
+
* This class used to override that with a 13-entry allowlist of model-name
|
|
67
|
+
* substrings, written for the old per-model Inference API where many
|
|
68
|
+
* endpoints rejected the OpenAI `tools` field. The router replaced that, and
|
|
69
|
+
* the list did not keep up. Measured against the 142 models
|
|
70
|
+
* `GET router.huggingface.co/v1/models` served on 2026-09-13 (the
|
|
71
|
+
* catalogue drifts, so treat the totals as a snapshot; the ratio is the
|
|
72
|
+
* point):
|
|
73
|
+
*
|
|
74
|
+
* allowlist entries matching ANY served model 1 of 13
|
|
75
|
+
* served models the allowlist ADMITS 1 of 142
|
|
76
|
+
* served models the allowlist BLOCKS 141
|
|
77
|
+
*
|
|
78
|
+
* So it suppressed tool calling for 99% of the catalogue, including
|
|
79
|
+
* Qwen/Qwen2.5-72B-Instruct, which the router demonstrably tool-calls. A
|
|
80
|
+
* spread of the blocked models ā GLM-5.3-Flash, gemma-4-31B-it,
|
|
81
|
+
* DeepSeek-V4-Flash ā all accept `tools` with HTTP 200 and return
|
|
82
|
+
* `tool_calls`; none rejected the field.
|
|
83
|
+
*
|
|
84
|
+
* The allowlist's own comment named `microsoft/DialoGPT-medium` ā which
|
|
85
|
+
* `getDefaultModel()`, not `getFallbackModelName()`, used to return ā as a
|
|
86
|
+
* model that rejects `tools`. The router does not serve it under any
|
|
87
|
+
* request shape, so that path was never reachable; the default now points
|
|
88
|
+
* at a served model (see `getDefaultHuggingFaceModel`).
|
|
89
|
+
*
|
|
90
|
+
* A model that genuinely cannot use tools simply does not emit `tool_calls`,
|
|
91
|
+
* which the loop already handles, so the optimistic default costs nothing
|
|
92
|
+
* that the allowlist was protecting.
|
|
56
93
|
*/
|
|
57
|
-
supportsTools() {
|
|
58
|
-
const modelName = this.modelName.toLowerCase();
|
|
59
|
-
const toolCapableModels = [
|
|
60
|
-
"llama-3.1-8b-instruct",
|
|
61
|
-
"llama-3.1-70b-instruct",
|
|
62
|
-
"llama-3.1-405b-instruct",
|
|
63
|
-
"llama-3.1-nemotron-ultra",
|
|
64
|
-
"hermes-3-llama-3.2",
|
|
65
|
-
"hermes-2-pro",
|
|
66
|
-
"codellama-34b-instruct",
|
|
67
|
-
"codellama-13b-instruct",
|
|
68
|
-
"mistral-7b-instruct-v0.3",
|
|
69
|
-
"mistral-8x7b-instruct",
|
|
70
|
-
"nous-hermes",
|
|
71
|
-
"openchat",
|
|
72
|
-
"wizardcoder",
|
|
73
|
-
];
|
|
74
|
-
return toolCapableModels.some((capable) => modelName.includes(capable));
|
|
75
|
-
}
|
|
76
94
|
formatProviderError(error) {
|
|
77
95
|
const rules = [
|
|
78
96
|
{
|
|
@@ -244,6 +244,27 @@ export declare abstract class OpenAIChatCompletionsProvider extends BaseProvider
|
|
|
244
244
|
*/
|
|
245
245
|
generate(optionsOrPrompt: TextGenerationOptions | string, analysisSchema?: ValidationSchema): Promise<EnhancedGenerateResult | null>;
|
|
246
246
|
private executeNativeGenerate;
|
|
247
|
+
/**
|
|
248
|
+
* Recover structured output on a turn where tools forced `response_format`
|
|
249
|
+
* off the wire.
|
|
250
|
+
*
|
|
251
|
+
* Runs only after the tool turn is complete, and only when its answer does
|
|
252
|
+
* not already satisfy the schema. The re-ask drops the tools, which is what
|
|
253
|
+
* makes native `response_format` legal again on a vendor that refuses the two
|
|
254
|
+
* together, so this is a formatting pass over an answer the model has already
|
|
255
|
+
* produced rather than a second attempt at the question.
|
|
256
|
+
*
|
|
257
|
+
* The schema is deliberately NOT spelled into the tool turn's system prompt
|
|
258
|
+
* instead. That was tried and reverted: a model handed a JSON Schema next to a
|
|
259
|
+
* tool list can read it as another tool ā Groq's llama-3.3 answers by calling
|
|
260
|
+
* one named "json", which the server rejects ā turning a wrong answer into a
|
|
261
|
+
* hard error.
|
|
262
|
+
*
|
|
263
|
+
* Returns the merged result, or the untouched `toolPhase` whenever the re-ask
|
|
264
|
+
* cannot be run or cannot be trusted, so it can improve an outcome but never
|
|
265
|
+
* degrade one.
|
|
266
|
+
*/
|
|
267
|
+
private reformatWithoutTools;
|
|
247
268
|
protected executeStream(options: StreamOptions, _analysisSchema?: ZodUnknownSchema | Schema<unknown>): Promise<StreamResult>;
|
|
248
269
|
private runStreamLoop;
|
|
249
270
|
private streamOneStep;
|