UNPKG

@juspay/neurolink

Version:

Universal AI Development Platform with working MCP integration, multi-provider support, and professional CLI. Built-in tools operational, 58+ external MCP servers discoverable. Connect to filesystem, GitHub, database operations, and more. Build, test, and

148 lines (147 loc) 6.08 kB
import { createOpenAI } from "@ai-sdk/openai"; import { streamText } from "ai"; import { BaseProvider } from "../core/baseProvider.js"; import { logger } from "../utils/logger.js"; import { createTimeoutController, TimeoutError, } from "../utils/timeout.js"; import { DEFAULT_MAX_TOKENS } from "../core/constants.js"; import { validateApiKey, createHuggingFaceConfig, getProviderModel, } from "../utils/providerConfig.js"; // Configuration helpers - now using consolidated utility const getHuggingFaceApiKey = () => { return validateApiKey(createHuggingFaceConfig()); }; const getDefaultHuggingFaceModel = () => { return getProviderModel("HUGGINGFACE_MODEL", "microsoft/DialoGPT-medium"); }; // Note: hasHuggingFaceCredentials now directly imported from consolidated utility /** * HuggingFace Provider - BaseProvider Implementation * Using AI SDK with HuggingFace's OpenAI-compatible endpoint */ export class HuggingFaceProvider extends BaseProvider { model; constructor(modelName) { super(modelName, "huggingface"); // Get API key and validate const apiKey = getHuggingFaceApiKey(); // Create HuggingFace provider using unified router endpoint (2025) const huggingface = createOpenAI({ apiKey: apiKey, baseURL: "https://router.huggingface.co/v1", }); // Initialize model this.model = huggingface(this.modelName); logger.debug("HuggingFaceProvider initialized", { model: this.modelName, provider: this.providerName, }); } // =================== // ABSTRACT METHOD IMPLEMENTATIONS // =================== /** * HuggingFace models currently don't properly support tool/function calling * * **Tested Models & Issues:** * - microsoft/DialoGPT-medium: Describes tools instead of executing them * - Most HF models via router endpoint: Function schema passed but not executed * - Issue: Models treat tool definitions as conversation context rather than executable functions * * **Known Limitations:** * - Tools are visible to model but treated as descriptive text * - No proper function call response format handling * - HuggingFace router endpoint doesn't enforce OpenAI-compatible tool execution * * @returns false to disable tools by default until proper implementation */ supportsTools() { // IMPLEMENTATION STATUS (2025): HuggingFace tool calling remains limited // // Current State: // - Function calling varies significantly across HF models // - Many models treat tool schemas as conversation context // - Requires model-specific implementation per architecture // // To Enable Tools: // 1. Detect model capability via HF model card metadata // 2. Implement model-specific tool schema formatting // 3. Add custom response parsing for function call extraction // 4. Create validation framework for tool parameter handling // 5. Test extensively with supported models (Code Llama, Llama 3.1+) // // Until comprehensive implementation, tools disabled for reliability return false; } // executeGenerate removed - BaseProvider handles all generation with tools async executeStream(options, analysisSchema) { this.validateStreamOptions(options); const timeout = this.getTimeout(options); const timeoutController = createTimeoutController(timeout, this.providerName, "stream"); try { const result = await streamText({ model: this.model, prompt: options.input.text, system: options.systemPrompt, temperature: options.temperature, maxTokens: options.maxTokens || DEFAULT_MAX_TOKENS, tools: options.tools, toolChoice: "auto", abortSignal: timeoutController?.controller.signal, }); timeoutController?.cleanup(); // Transform stream to match StreamResult interface const transformedStream = async function* () { for await (const chunk of result.textStream) { yield { content: chunk }; } }; return { stream: transformedStream(), provider: this.providerName, model: this.modelName, }; } catch (error) { timeoutController?.cleanup(); throw this.handleProviderError(error); } } getProviderName() { return "huggingface"; } getDefaultModel() { return getDefaultHuggingFaceModel(); } /** * Returns the Vercel AI SDK model instance for HuggingFace */ getAISDKModel() { return this.model; } handleProviderError(error) { if (error instanceof TimeoutError) { return new Error(`HuggingFace request timed out: ${error.message}`); } const errorObj = error; const message = errorObj?.message && typeof errorObj.message === "string" ? errorObj.message : "Unknown error"; if (message.includes("API_TOKEN_INVALID") || message.includes("Invalid token")) { return new Error("Invalid HuggingFace API token. Please check your HUGGING_FACE_API_KEY environment variable."); } if (message.includes("rate limit")) { return new Error("HuggingFace rate limit exceeded. Please try again later."); } return new Error(`HuggingFace error: ${message}`); } // =================== // PRIVATE VALIDATION METHODS // =================== validateStreamOptions(options) { if (!options.input?.text || options.input.text.trim().length === 0) { throw new Error("Input text is required and cannot be empty"); } } } // Export for factory registration export default HuggingFaceProvider;