From 0745a31af508c8840511045a4d7b8aa5bfb50306 Mon Sep 17 00:00:00 2001 From: Forhad Hosain Date: Tue, 31 Mar 2026 21:56:58 +0600 Subject: [PATCH 1/5] sync hugging-face.params.json with SRE one --- .../params/hugging-face.params.json | 283 +++++++++++++----- 1 file changed, 211 insertions(+), 72 deletions(-) diff --git a/packages/app/src/builder-ui/params/hugging-face.params.json b/packages/app/src/builder-ui/params/hugging-face.params.json index c324c639d..184c96787 100644 --- a/packages/app/src/builder-ui/params/hugging-face.params.json +++ b/packages/app/src/builder-ui/params/hugging-face.params.json @@ -8,6 +8,32 @@ "request_parameter_type": "string" } }, + "parameters": { + "top_k": { + "type": "number", + "default": "None", + "desc": "(Default: None). When specified, limits the output to the top K most probable labels." + }, + "function_to_apply": { + "type": "string", + "default": "None", + "desc": "(Default: None). The function to apply to the model outputs to retrieve the scores.", + "supportedValues": [ + { + "value": "sigmoid", + "desc": "Applies the Sigmoid function to the output." + }, + { + "value": "softmax", + "desc": "Applies the Softmax function to the output." + }, + { + "value": "none", + "desc": "Does not apply any function to the output." + } + ] + } + }, "formatRequest": "inputs: \"{{text}}\"" }, "token-classification": { @@ -46,6 +72,16 @@ "desc": "Same as the simple strategy except words cannot end up with different tags. Word entity will be the token with the maximum score." } ] + }, + "ignore_labels": { + "type": "string[]", + "default": [], + "desc": "(Default: []). A list of labels to ignore in the results." + }, + "stride": { + "type": "number", + "default": "None", + "desc": "(Default: None). The number of overlapping tokens between chunks when splitting the input text." } }, "formatRequest": "inputs: \"{{text}}\"" @@ -80,6 +116,43 @@ "request_parameter_type": "string" } }, + "parameters": { + "top_k": { + "type": "number", + "default": "None", + "desc": "(Default: None). The number of answers to return (will be sorted by likelihood). Note that we return less than topk answers if there are not enough options available within the context." + }, + "doc_stride": { + "type": "number", + "default": "None", + "desc": "(Default: None). If the context is too long to fit with the question for the model, it will be split into overlapping chunks. This argument controls the size of that overlap." + }, + "max_answer_len": { + "type": "number", + "default": "None", + "desc": "(Default: None). The maximum length of the predicted answer." + }, + "max_seq_len": { + "type": "number", + "default": "None", + "desc": "(Default: None). The maximum length of the total sentence (context + question) after tokenization." + }, + "max_question_len": { + "type": "number", + "default": "None", + "desc": "(Default: None). The maximum length of the question after tokenization." + }, + "handle_impossible_answer": { + "type": "boolean", + "default": false, + "desc": "(Default: false). Whether to accept impossible as an answer." + }, + "align_to_words": { + "type": "boolean", + "default": "None", + "desc": "(Default: None). Attempts to align the answer to real words. Improves quality on space separated languages." + } + }, "formatRequest": "inputs: { context: \"{{context}}\", question: \"{{question}}\" }" }, "document-question-answering": { @@ -97,6 +170,33 @@ "request_parameter_type": "string" } }, + "parameters": { + "doc_stride": { + "type": "number", + "default": "None", + "desc": "(Default: None). If the words in the document are too long to fit with the question for the model, it will be split into overlapping chunks. This argument controls the size of that overlap." + }, + "handle_impossible_answer": { + "type": "boolean", + "default": false, + "desc": "(Default: false). Whether to accept impossible as an answer." + }, + "lang": { + "type": "string", + "default": "None", + "desc": "(Default: None). Language of the document (e.g. 'en', 'fr'). Used for OCR preprocessing of the image." + }, + "max_answer_len": { + "type": "number", + "default": "None", + "desc": "(Default: None). The maximum length of the predicted answer." + }, + "word_boxes": { + "type": "object[]", + "default": "None", + "desc": "(Default: None). A list of word boxes and their associated words. If provided, the image is not used for OCR." + } + }, "formatRequest": "inputs: { image: {{image}}, question: \"{{question}}\" }" }, "visual-question-answering": { @@ -148,6 +248,28 @@ "request_parameter_type": "string" } }, + "parameters": { + "src_lang": { + "type": "string", + "default": "None", + "desc": "(Default: None). Source language code (e.g. 'en'). Required for multilingual translation models." + }, + "tgt_lang": { + "type": "string", + "default": "None", + "desc": "(Default: None). Target language code (e.g. 'fr'). Required for multilingual translation models." + }, + "clean_up_tokenization_spaces": { + "type": "boolean", + "default": "None", + "desc": "(Default: None). Whether to clean up the potential extra spaces in the text output." + }, + "truncation": { + "type": "string", + "default": "None", + "desc": "(Default: None). The truncation strategy to use." + } + }, "formatRequest": "inputs: \"{{text}}\"" }, "summarization": { @@ -200,63 +322,46 @@ }, "conversational": { "inputs": { - "Text": { - "type": "string", - "desc": "(required) The last input from the user in the conversation.", - "request_parameter_name": "text", - "request_parameter_type": "string" - }, - "Generated_responses": { - "type": "string[]", - "desc": "A list of strings corresponding to the earlier replies from the model.", - "request_parameter_name": "generated_responses", - "request_parameter_type": "string[]" - }, - "Past_user_inputs": { - "type": "string[]", - "desc": "A list of strings corresponding to the earlier replies from the user. Should be of the same length of generated_responses.", - "request_parameter_name": "past_user_inputs", - "request_parameter_type": "string[]" + "Messages": { + "type": "object[]", + "desc": "(required) A list of messages comprising the conversation so far. Each message is an object with 'role' (e.g. 'user', 'assistant', 'system') and 'content' (string).", + "request_parameter_name": "messages", + "request_parameter_type": "object[]" } }, "parameters": { - "min_length": { - "type": "number", - "default": "None", - "desc": "(Default: None). Integer to define the minimum length in tokens of the output summary." - }, - "max_length": { + "max_tokens": { "type": "number", "default": "None", - "desc": "(Default: None). Integer to define the maximum length in tokens of the output summary." + "desc": "(Default: None). The maximum number of tokens that can be generated in the chat completion." }, - "top_k": { + "temperature": { "type": "number", - "default": "None", - "desc": "(Default: None). Integer to define the top tokens considered within the sample operation to create new text." + "default": 1, + "desc": "(Default: 1.0). Float (0.0-2.0). Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic." }, "top_p": { "type": "number", "default": "None", - "desc": "(Default: None). Float to define the tokens that are within the sample operation of text generation. Add tokens in the sample for more probable to least probable until the sum of the probabilities is greater than top_p." + "desc": "(Default: None). Float. An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass." }, - "temperature": { + "frequency_penalty": { "type": "number", - "default": 1, - "desc": "(Default: 1.0). Float (0.0-100.0). The temperature of the sampling operation. 1 means regular sampling, 0 means always take the highest score, 100.0 is getting closer to uniform probability." + "default": "None", + "desc": "(Default: None). Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far." }, - "repetition_penalty": { + "presence_penalty": { "type": "number", "default": "None", - "desc": "(Default: None). Float (0.0-100.0). The more a token is used within generation the more it is penalized to not be picked in successive generation passes." + "desc": "(Default: None). Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far." }, - "max_time": { - "type": "number", + "stop": { + "type": "string[]", "default": "None", - "desc": "(Default: None). Float (0-120.0). The amount of time in seconds that the query should take maximum. Network can cause some overhead so it will be a soft limit." + "desc": "(Default: None). Up to 4 sequences where the API will stop generating further tokens." } }, - "formatRequest": "inputs: \"{{text}}\", past_user_inputs: [{{past_user_inputs}}], generated_responses: [{{generated_responses}}] }" + "formatRequest": "messages: [{{messages}}]" }, "text-generation": { "inputs": { @@ -268,55 +373,35 @@ } }, "parameters": { - "do_sample": { - "type": "boolean", - "default": true, - "desc": "(Optional: true). Bool. Whether or not to use sampling, use greedy decoding otherwise." - }, - "max_time": { + "max_tokens": { "type": "number", "default": "None", - "desc": "(Default: None). Float (0-120.0). The amount of time in seconds that the query should take maximum. Network can cause some overhead so it will be a soft limit." - }, - "num_return_sequences": { - "type": "number", - "default": 1, - "desc": "(Default: 1). Integer. The number of proposition you want to be returned." - }, - "repetition_penalty": { - "type": "number", - "default": "None", - "desc": "(Default: None). Float (0.0-100.0). The more a token is used within generation the more it is penalized to not be picked in successive generation passes." - }, - "return_full_text": { - "type": "boolean", - "default": true, - "desc": "(Default: true). Bool. If set to False, the return results will not contain the original query making it easier for prompting." + "desc": "(Default: None). The maximum number of tokens that can be generated in the completion." }, "temperature": { "type": "number", "default": 1, - "desc": "(Default: 1.0). Float (0.0-100.0). The temperature of the sampling operation. 1 means regular sampling, 0 means always take the highest score, 100.0 is getting closer to uniform probability." + "desc": "(Default: 1.0). Float (0.0-2.0). Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic." }, - "max_new_tokens": { + "top_p": { "type": "number", "default": "None", - "desc": "(Default: None). Int (0-250). The amount of new tokens to be generated, this does not include the input length it is a estimate of the size of generated text you want. Each new tokens slows down the request, so look for balance between response times and length of text generated." + "desc": "(Default: None). Float. An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass." }, - "top_k": { + "frequency_penalty": { "type": "number", "default": "None", - "desc": "(Default: None). Integer to define the top tokens considered within the sample operation to create new text." + "desc": "(Default: None). Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far." }, - "top_p": { + "presence_penalty": { "type": "number", "default": "None", - "desc": "(Default: None). Float to define the tokens that are within the sample operation of text generation. Add tokens in the sample for more probable to least probable until the sum of the probabilities is greater than top_p." + "desc": "(Default: None). Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far." }, - "truncate": { - "type": "number", + "stop": { + "type": "string[]", "default": "None", - "desc": "(Default: None). Integer. The maximum number of tokens from the input." + "desc": "(Default: None). Up to 4 sequences where the API will stop generating further tokens." } }, "formatRequest": "inputs: \"{{text}}\"" @@ -406,6 +491,38 @@ "request_parameter_type": "string" } }, + "parameters": { + "negative_prompt": { + "type": "string", + "default": "None", + "desc": "(Default: None). A text specifying what the model should NOT generate." + }, + "height": { + "type": "number", + "default": "None", + "desc": "(Default: None). The height in pixels of the generated image." + }, + "width": { + "type": "number", + "default": "None", + "desc": "(Default: None). The width in pixels of the generated image." + }, + "num_inference_steps": { + "type": "number", + "default": "None", + "desc": "(Default: None). The number of denoising steps. More denoising steps usually lead to a higher quality image at the expense of slower inference." + }, + "guidance_scale": { + "type": "number", + "default": "None", + "desc": "(Default: None). Higher guidance scale encourages to generate images that are closely linked to the text prompt, usually at the expense of lower image quality." + }, + "seed": { + "type": "number", + "default": "None", + "desc": "(Default: None). A random seed for reproducibility. Using the same seed with the same parameters will produce the same image." + } + }, "formatRequest": "inputs: \"{{text}}\"" }, "image-to-text": { @@ -446,11 +563,11 @@ "Image": { "type": "URL | base64 | file | SmythFileObject", "desc": "(required) image URL, base64 string, uploaded image, or linked image output", - "request_parameter_name": "data", + "request_parameter_name": "inputs", "request_parameter_type": "Blob | ArrayBuffer" } }, - "formatRequest": "data: {{image}}" + "formatRequest": "inputs: {{image}}" }, "zero-shot-image-classification": { "inputs": { @@ -575,6 +692,28 @@ "request_parameter_type": "string | string[]" } }, + "parameters": { + "normalize": { + "type": "boolean", + "default": "None", + "desc": "(Default: None). Whether to normalize the output embeddings to unit length." + }, + "prompt_name": { + "type": "string", + "default": "None", + "desc": "(Default: None). The name of the prompt that should be used by for encoding (e.g. 'query', 'passage'). If not set, no prompt is applied." + }, + "truncate": { + "type": "boolean", + "default": "None", + "desc": "(Default: None). Whether to truncate inputs longer than the model's maximum context length." + }, + "truncation_direction": { + "type": "string", + "default": "Right", + "desc": "(Default: Right). The truncation direction: 'Left' or 'Right'." + } + }, "formatRequest": "inputs: \"{{text}}\"" } -} \ No newline at end of file +} From 2b020f022c8d28a1086c228edfdf4913421c2286 Mon Sep 17 00:00:00 2001 From: Forhad Hosain Date: Tue, 31 Mar 2026 23:28:23 +0600 Subject: [PATCH 2/5] sync hugging face params with SRE --- .../params/hugging-face.params.json | 555 +++++++++++++++--- 1 file changed, 488 insertions(+), 67 deletions(-) diff --git a/packages/app/src/builder-ui/params/hugging-face.params.json b/packages/app/src/builder-ui/params/hugging-face.params.json index 184c96787..36f1d7413 100644 --- a/packages/app/src/builder-ui/params/hugging-face.params.json +++ b/packages/app/src/builder-ui/params/hugging-face.params.json @@ -101,6 +101,37 @@ "request_parameter_type": "Record" } }, + "parameters": { + "padding": { + "type": "string", + "default": "None", + "desc": "(Default: None). Padding strategy for the input.", + "supportedValues": [ + { + "value": "do_not_pad", + "desc": "Do not pad the input." + }, + { + "value": "longest", + "desc": "Pad to the longest sequence in the batch." + }, + { + "value": "max_length", + "desc": "Pad to the maximum length." + } + ] + }, + "sequential": { + "type": "boolean", + "default": false, + "desc": "(Default: false). Whether to do inference sequentially or as a batch. Batching is faster, but models like SQA require sequential inference to extract relations within sequences." + }, + "truncation": { + "type": "boolean", + "default": false, + "desc": "(Default: false). Activates and controls truncation." + } + }, "formatRequest": "inputs: { query: \"{{query}}\", table: {{table}} }" }, "question-answering": { @@ -235,6 +266,11 @@ "type": "boolean", "default": false, "desc": "(Default: false) Boolean that is set to True if classes can overlap" + }, + "hypothesis_template": { + "type": "string", + "default": "None", + "desc": "(Default: None). The sentence used in conjunction with candidate_labels to attempt the text classification by replacing the placeholder with the candidate labels." } }, "formatRequest": "inputs: \"{{text}}\", parameters: { candidate_labels: [{{candidate_labels}}] }" @@ -252,12 +288,12 @@ "src_lang": { "type": "string", "default": "None", - "desc": "(Default: None). Source language code (e.g. 'en'). Required for multilingual translation models." + "desc": "(Default: None). The source language of the text. Required for models that can translate from multiple languages." }, "tgt_lang": { "type": "string", "default": "None", - "desc": "(Default: None). Target language code (e.g. 'fr'). Required for multilingual translation models." + "desc": "(Default: None). Target language to translate to. Required for models that can translate to multiple languages." }, "clean_up_tokenization_spaces": { "type": "boolean", @@ -267,7 +303,30 @@ "truncation": { "type": "string", "default": "None", - "desc": "(Default: None). The truncation strategy to use." + "desc": "(Default: None). The truncation strategy to use.", + "supportedValues": [ + { + "value": "do_not_truncate", + "desc": "Do not truncate the input." + }, + { + "value": "longest_first", + "desc": "Truncate the longest sequence first." + }, + { + "value": "only_first", + "desc": "Truncate only the first sequence." + }, + { + "value": "only_second", + "desc": "Truncate only the second sequence." + } + ] + }, + "generate_parameters": { + "type": "object", + "default": "None", + "desc": "(Default: None). Additional parametrization of the text generation algorithm." } }, "formatRequest": "inputs: \"{{text}}\"" @@ -282,40 +341,38 @@ } }, "parameters": { - "min_length": { - "type": "number", - "default": "None", - "desc": "(Default: None). Integer to define the minimum length in tokens of the output summary." - }, - "max_length": { - "type": "number", - "default": "None", - "desc": "(Default: None). Integer to define the maximum length in tokens of the output summary." - }, - "top_k": { - "type": "number", - "default": "None", - "desc": "(Default: None). Integer to define the top tokens considered within the sample operation to create new text." - }, - "top_p": { - "type": "number", + "clean_up_tokenization_spaces": { + "type": "boolean", "default": "None", - "desc": "(Default: None). Float to define the tokens that are within the sample operation of text generation. Add tokens in the sample for more probable to least probable until the sum of the probabilities is greater than top_p." - }, - "temperature": { - "type": "number", - "default": 1, - "desc": "(Default: 1.0). Float (0.0-100.0). The temperature of the sampling operation. 1 means regular sampling, 0 means always take the highest score, 100.0 is getting closer to uniform probability." + "desc": "(Default: None). Whether to clean up the potential extra spaces in the text output." }, - "repetition_penalty": { - "type": "number", + "truncation": { + "type": "string", "default": "None", - "desc": "(Default: None). Float (0.0-100.0). The more a token is used within generation the more it is penalized to not be picked in successive generation passes." + "desc": "(Default: None). The truncation strategy to use.", + "supportedValues": [ + { + "value": "do_not_truncate", + "desc": "Do not truncate the input." + }, + { + "value": "longest_first", + "desc": "Truncate the longest sequence first." + }, + { + "value": "only_first", + "desc": "Truncate only the first sequence." + }, + { + "value": "only_second", + "desc": "Truncate only the second sequence." + } + ] }, - "max_time": { - "type": "number", + "generate_parameters": { + "type": "object", "default": "None", - "desc": "(Default: None). Float (0-120.0). The amount of time in seconds that the query should take maximum. Network can cause some overhead so it will be a soft limit." + "desc": "(Default: None). Additional parametrization of the text generation algorithm." } }, "formatRequest": "inputs: \"{{text}}\"" @@ -359,6 +416,62 @@ "type": "string[]", "default": "None", "desc": "(Default: None). Up to 4 sequences where the API will stop generating further tokens." + }, + "logprobs": { + "type": "boolean", + "default": false, + "desc": "(Default: false). Whether to return log probabilities of the output tokens or not. If true, returns the log probabilities of each output token returned in the content of message." + }, + "top_logprobs": { + "type": "number", + "default": "None", + "desc": "(Default: None). An integer between 0 and 5 specifying the number of most likely tokens to return at each token position, each with an associated log probability. logprobs must be set to true if this parameter is used." + }, + "seed": { + "type": "number", + "default": "None", + "desc": "(Default: None). Seed for the random number generator for reproducibility." + }, + "stream": { + "type": "boolean", + "default": false, + "desc": "(Default: false). If set, partial message deltas will be sent as Server-Sent Events (SSE)." + }, + "stream_options": { + "type": "object", + "default": "None", + "desc": "(Default: None). Options for streaming. Only set this when stream is true.", + "properties": { + "include_usage": { + "type": "boolean", + "desc": "If set, an additional chunk will be streamed with token usage statistics for the entire request." + } + } + }, + "reasoning_effort": { + "type": "string", + "default": "None", + "desc": "(Default: None). Constrains effort on reasoning for models that support it. Reducing reasoning effort can result in faster responses and fewer tokens used. Common values: none, minimal, low, medium, high, xhigh. Support and defaults are provider and model-dependent." + }, + "response_format": { + "type": "object", + "default": "None", + "desc": "(Default: None). The format of the response. Can be 'text', 'json_object', or 'json_schema' with a schema definition." + }, + "tool_choice": { + "type": "string", + "default": "None", + "desc": "(Default: None). Controls which (if any) tool the model should use. Can be 'auto', 'none', 'required', or an object specifying a function." + }, + "tool_prompt": { + "type": "string", + "default": "None", + "desc": "(Default: None). A prompt to be appended before the tools." + }, + "tools": { + "type": "object[]", + "default": "None", + "desc": "(Default: None). A list of tools the model may call. Currently, only functions are supported as a tool. Use this to provide a list of functions the model may generate JSON inputs for." } }, "formatRequest": "messages: [{{messages}}]" @@ -373,35 +486,105 @@ } }, "parameters": { - "max_tokens": { + "max_new_tokens": { "type": "number", "default": "None", - "desc": "(Default: None). The maximum number of tokens that can be generated in the completion." + "desc": "(Default: None). Maximum number of tokens to generate." }, "temperature": { "type": "number", - "default": 1, - "desc": "(Default: 1.0). Float (0.0-2.0). Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic." + "default": "None", + "desc": "(Default: None). The value used to modulate the logits distribution." }, "top_p": { "type": "number", "default": "None", - "desc": "(Default: None). Float. An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass." + "desc": "(Default: None). Top-p value for nucleus sampling." + }, + "top_k": { + "type": "number", + "default": "None", + "desc": "(Default: None). The number of highest probability vocabulary tokens to keep for top-k-filtering." }, "frequency_penalty": { "type": "number", "default": "None", - "desc": "(Default: None). Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far." + "desc": "(Default: None). The parameter for frequency penalty. 1.0 means no penalty. Penalize new tokens based on their existing frequency in the text so far." }, - "presence_penalty": { + "repetition_penalty": { "type": "number", "default": "None", - "desc": "(Default: None). Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far." + "desc": "(Default: None). The parameter for repetition penalty. 1.0 means no penalty." + }, + "do_sample": { + "type": "boolean", + "default": false, + "desc": "(Default: false). Activate logits sampling." }, "stop": { "type": "string[]", "default": "None", - "desc": "(Default: None). Up to 4 sequences where the API will stop generating further tokens." + "desc": "(Default: None). Stop generating tokens if a member of stop is generated." + }, + "seed": { + "type": "number", + "default": "None", + "desc": "(Default: None). Random sampling seed." + }, + "return_full_text": { + "type": "boolean", + "default": "None", + "desc": "(Default: None). Whether to prepend the prompt to the generated text." + }, + "truncate": { + "type": "number", + "default": "None", + "desc": "(Default: None). Truncate inputs tokens to the given size." + }, + "typical_p": { + "type": "number", + "default": "None", + "desc": "(Default: None). Typical Decoding mass. See Typical Decoding for Natural Language Generation for more information." + }, + "watermark": { + "type": "boolean", + "default": false, + "desc": "(Default: false). Watermarking with A Watermark for Large Language Models." + }, + "details": { + "type": "boolean", + "default": false, + "desc": "(Default: false). Whether to return generation details." + }, + "decoder_input_details": { + "type": "boolean", + "default": false, + "desc": "(Default: false). Whether to return decoder input token logprobs and ids." + }, + "best_of": { + "type": "number", + "default": "None", + "desc": "(Default: None). Generate best_of sequences and return the one with the highest token logprobs." + }, + "top_n_tokens": { + "type": "number", + "default": "None", + "desc": "(Default: None). The number of highest probability vocabulary tokens to keep for top-n-filtering." + }, + "adapter_id": { + "type": "string", + "default": "None", + "desc": "(Default: None). Lora adapter id." + }, + "grammar": { + "type": "object", + "default": "None", + "desc": "(Default: None). Grammar constraints for the output. Can be a JSON schema, regex, or json_schema type." + }, + "stream": { + "type": "boolean", + "default": false, + "desc": "(Default: false). Whether to stream the output tokens." } }, "formatRequest": "inputs: \"{{text}}\"" @@ -463,6 +646,18 @@ "request_parameter_type": "string" } }, + "parameters": { + "top_k": { + "type": "number", + "default": "None", + "desc": "(Default: None). When passed, overrides the number of predictions to return." + }, + "targets": { + "type": "string[]", + "default": "None", + "desc": "(Default: None). When passed, the model will limit the scores to the passed targets instead of looking up in the whole vocabulary." + } + }, "formatRequest": "inputs: \"{{text}}\"" }, "sentence-similarity": { @@ -521,6 +716,11 @@ "type": "number", "default": "None", "desc": "(Default: None). A random seed for reproducibility. Using the same seed with the same parameters will produce the same image." + }, + "scheduler": { + "type": "string", + "default": "None", + "desc": "(Default: None). Override the scheduler with a compatible one." } }, "formatRequest": "inputs: \"{{text}}\"" @@ -545,6 +745,32 @@ "request_parameter_type": "Blob | ArrayBuffer" } }, + "parameters": { + "function_to_apply": { + "type": "string", + "default": "None", + "desc": "(Default: None). The function to apply to the model outputs to retrieve the scores.", + "supportedValues": [ + { + "value": "sigmoid", + "desc": "Applies the Sigmoid function to the output." + }, + { + "value": "softmax", + "desc": "Applies the Softmax function to the output." + }, + { + "value": "none", + "desc": "Does not apply any function to the output." + } + ] + }, + "top_k": { + "type": "number", + "default": "None", + "desc": "(Default: None). When specified, limits the output to the top K most probable classes." + } + }, "formatRequest": "data: {{image}}" }, "object-detection": { @@ -556,6 +782,13 @@ "request_parameter_type": "Blob | ArrayBuffer" } }, + "parameters": { + "threshold": { + "type": "number", + "default": "None", + "desc": "(Default: None). The probability necessary to make a prediction." + } + }, "formatRequest": "data: {{image}}" }, "image-segmentation": { @@ -567,6 +800,42 @@ "request_parameter_type": "Blob | ArrayBuffer" } }, + "parameters": { + "mask_threshold": { + "type": "number", + "default": "None", + "desc": "(Default: None). Threshold to use when turning the predicted masks into binary values." + }, + "overlap_mask_area_threshold": { + "type": "number", + "default": "None", + "desc": "(Default: None). Mask overlap threshold to eliminate small, disconnected segments." + }, + "subtask": { + "type": "string", + "default": "None", + "desc": "(Default: None). Segmentation subtask.", + "supportedValues": [ + { + "value": "instance", + "desc": "Instance segmentation." + }, + { + "value": "panoptic", + "desc": "Panoptic segmentation." + }, + { + "value": "semantic", + "desc": "Semantic segmentation." + } + ] + }, + "threshold": { + "type": "number", + "default": "None", + "desc": "(Default: None). Probability threshold to filter out predicted masks." + } + }, "formatRequest": "inputs: {{image}}" }, "zero-shot-image-classification": { @@ -598,43 +867,38 @@ "parameters": { "prompt": { "type": "string", - "desc": "(Optional) The text prompt to guide the image generation", + "desc": "(Optional) The text prompt to guide the image generation.", "default": "None" }, - "strength": { + "guidance_scale": { "type": "number", - "default": 0, - "desc": "(Optional) The 'strength' parameter is effective only for SD img2img and alt diffusion img2img models. It conceptually indicates the extent of transformation applied to the reference 'image,' with values between 0 and 1. A higher 'strength' adds more noise to the initial 'image,' and the denoising process runs for the specified number of iterations in 'num_inference_steps.' A 'strength' of 1 ignores the 'image,' applying maximum added noise and running denoising for the full set of iterations." + "default": "None", + "desc": "(Default: None). For diffusion models. A higher guidance scale value encourages the model to generate images closely linked to the text prompt at the expense of lower image quality." }, "negative_prompt": { "type": "string", "default": "None", - "desc": "(Optional) A negative prompt for the image generation" - }, - "height": { - "type": "number", - "default": "None", - "desc": "(Optional) The height in pixels of the generated image" - }, - "width": { - "type": "number", - "default": "None", - "desc": "(Optional) The width in pixels of the generated image" + "desc": "(Default: None). One prompt to guide what NOT to include in image generation." }, "num_inference_steps": { "type": "number", "default": "None", - "desc": "(Optional) The number of denoising steps. More denoising steps usually lead to a higher quality image at the expense of slower inference." + "desc": "(Default: None). For diffusion models. The number of denoising steps. More denoising steps usually lead to a higher quality image at the expense of slower inference." }, - "guidance_scale": { - "type": "number", - "default": "None", - "desc": "(Optional) Guidance scale: Higher guidance scale encourages to generate images that are closely linked to the text `prompt`, usually at the expense of lower image quality." - }, - "guess_mode": { - "type": "boolean", + "target_size": { + "type": "object", "default": "None", - "desc": "(Optional) guess_mode only works for ControlNet models, defaults to False In this mode, the ControlNet encoder will try best to recognize the content of the input image even if you remove all prompts. The `guidance_scale` between 3.0 and 5.0 is recommended." + "desc": "(Default: None). The size in pixels of the output image. This parameter is only supported by some providers and for specific models.", + "properties": { + "width": { + "type": "number", + "desc": "(required) The width in pixels of the output image." + }, + "height": { + "type": "number", + "desc": "(required) The height in pixels of the output image." + } + } } }, "formatRequest": "inputs: {{image}}" @@ -659,6 +923,89 @@ "request_parameter_type": "Blob | ArrayBuffer" } }, + "parameters": { + "return_timestamps": { + "type": "boolean", + "default": false, + "desc": "(Default: false). Whether to output corresponding timestamps with the generated text." + }, + "generation_parameters": { + "type": "object", + "default": "None", + "desc": "(Default: None). Additional parametrization of the text generation algorithm.", + "properties": { + "temperature": { + "type": "number", + "desc": "The value used to modulate the next token probabilities." + }, + "top_k": { + "type": "number", + "desc": "The number of highest probability vocabulary tokens to keep for top-k-filtering." + }, + "top_p": { + "type": "number", + "desc": "If set to float < 1, only the smallest set of most probable tokens with probabilities that add up to top_p or higher are kept for generation." + }, + "typical_p": { + "type": "number", + "desc": "Local typicality measure. If set to float < 1, the smallest set of the most locally typical tokens with probabilities that add up to typical_p or higher are kept for generation." + }, + "epsilon_cutoff": { + "type": "number", + "desc": "If set to float strictly between 0 and 1, only tokens with a conditional probability greater than epsilon_cutoff will be sampled." + }, + "eta_cutoff": { + "type": "number", + "desc": "Eta sampling is a hybrid of locally typical sampling and epsilon sampling." + }, + "max_length": { + "type": "number", + "desc": "The maximum length (in tokens) of the generated text, including the input." + }, + "max_new_tokens": { + "type": "number", + "desc": "The maximum number of tokens to generate. Takes precedence over max_length." + }, + "min_length": { + "type": "number", + "desc": "The minimum length (in tokens) of the generated text, including the input." + }, + "min_new_tokens": { + "type": "number", + "desc": "The minimum number of tokens to generate. Takes precedence over min_length." + }, + "do_sample": { + "type": "boolean", + "desc": "Whether to use sampling instead of greedy decoding when generating new tokens." + }, + "early_stopping": { + "type": "string", + "desc": "Controls the stopping condition for beam-based methods.", + "supportedValues": [ + { "value": "never", "desc": "Never stop early." }, + { "value": "true", "desc": "Stop as soon as num_beams complete sentences are found." }, + { "value": "false", "desc": "Apply default stopping condition." } + ] + }, + "num_beams": { + "type": "number", + "desc": "Number of beams to use for beam search." + }, + "num_beam_groups": { + "type": "number", + "desc": "Number of groups to divide num_beams into to ensure diversity among different groups of beams." + }, + "penalty_alpha": { + "type": "number", + "desc": "The value balances the model confidence and the degeneration penalty in contrastive search decoding." + }, + "use_cache": { + "type": "boolean", + "desc": "Whether the model should use the past last key/values attentions to speed up decoding." + } + } + } + }, "formatRequest": "data: {{audio}}" }, "audio-to-audio": { @@ -681,8 +1028,72 @@ "request_parameter_type": "Blob | ArrayBuffer" } }, + "parameters": { + "function_to_apply": { + "type": "string", + "default": "None", + "desc": "(Default: None). The function to apply to the model outputs to retrieve the scores.", + "supportedValues": [ + { + "value": "sigmoid", + "desc": "Applies the Sigmoid function to the output." + }, + { + "value": "softmax", + "desc": "Applies the Softmax function to the output." + }, + { + "value": "none", + "desc": "Does not apply any function to the output." + } + ] + }, + "top_k": { + "type": "number", + "default": "None", + "desc": "(Default: None). When specified, limits the output to the top K most probable classes." + } + }, "formatRequest": "data: {{audio}}" }, + "text-to-video": { + "inputs": { + "Text": { + "type": "string", + "desc": "(required) prompt to generate video from", + "request_parameter_name": "inputs", + "request_parameter_type": "string" + } + }, + "parameters": { + "num_frames": { + "type": "number", + "default": "None", + "desc": "(Default: None). The number of video frames to generate." + }, + "guidance_scale": { + "type": "number", + "default": "None", + "desc": "(Default: None). A higher guidance scale value encourages the model to generate videos closely linked to the text prompt, but values too high may cause saturation and other artifacts." + }, + "negative_prompt": { + "type": "string[]", + "default": "None", + "desc": "(Default: None). One or several prompts to guide what NOT to include in video generation." + }, + "num_inference_steps": { + "type": "number", + "default": "None", + "desc": "(Default: None). The number of denoising steps. More denoising steps usually lead to a higher quality video at the expense of slower inference." + }, + "seed": { + "type": "number", + "default": "None", + "desc": "(Default: None). Seed for the random number generator." + } + }, + "formatRequest": "inputs: \"{{text}}\"" + }, "feature-extraction": { "inputs": { "Text": { @@ -710,8 +1121,18 @@ }, "truncation_direction": { "type": "string", - "default": "Right", - "desc": "(Default: Right). The truncation direction: 'Left' or 'Right'." + "default": "right", + "desc": "(Default: right). The truncation direction.", + "supportedValues": [ + { + "value": "left", + "desc": "Truncate from the left (beginning) of the input." + }, + { + "value": "right", + "desc": "Truncate from the right (end) of the input." + } + ] } }, "formatRequest": "inputs: \"{{text}}\"" From 8abc7a19ea8d434482ef9b1a5d63cd5fa8e8591a Mon Sep 17 00:00:00 2001 From: Forhad Hosain Date: Thu, 2 Apr 2026 12:43:33 +0600 Subject: [PATCH 3/5] find out effective tasks of HF model and fix fetching models fetching issue --- .../backend/services/huggingFace.service.ts | 64 +++++++++++++++++-- .../components/HuggingFace.class.ts | 6 +- 2 files changed, 60 insertions(+), 10 deletions(-) diff --git a/packages/app/src/backend/services/huggingFace.service.ts b/packages/app/src/backend/services/huggingFace.service.ts index 8dc14d293..9c54b22e3 100644 --- a/packages/app/src/backend/services/huggingFace.service.ts +++ b/packages/app/src/backend/services/huggingFace.service.ts @@ -1,4 +1,6 @@ import axios from 'axios'; +import http from 'http'; +import https from 'https'; import { load as cheerioLoad } from 'cheerio'; import he from 'he'; @@ -9,13 +11,22 @@ import * as openai from './openai-helper'; import Cache from './Cache.class'; import Store from './Store.class'; +// Increase the Happy Eyeballs (autoSelectFamily) timeout from the default 250ms to 2000ms. +// On networks with broken IPv6, the default 250ms is too short for the IPv4 fallback to +// connect before the failed IPv6 attempt aborts the whole connection. +const hfAxios = axios.create({ + timeout: 30000, + httpAgent: new http.Agent({ keepAlive: true, autoSelectFamilyAttemptTimeout: 2000 }), + httpsAgent: new https.Agent({ keepAlive: true, autoSelectFamilyAttemptTimeout: 2000 }), +}); + const modelInfoCache = new Cache({ directory: 'hf-model-info' }); const modelResultCache = new Cache({ directory: 'hf-model-result' }); const store = new Store('huggingFace/leftover-result'); const _getModelLogo = async (modelName: string): Promise => { try { - const res = await axios.get(`https://huggingface.co/${modelName}`); + const res = await hfAxios.get(`https://huggingface.co/${modelName}`); const $ = await cheerioLoad(res?.data); const imageElement = $('main header h1 > div:first-child > div:first-child img'); @@ -70,7 +81,7 @@ type ModelInfo = { */ const _crawlModelInfo = async (modelName: string): Promise => { try { - const res = await axios.get(`https://huggingface.co/${modelName}`); + const res = await hfAxios.get(`https://huggingface.co/${modelName}`); const $ = await cheerioLoad(res?.data); @@ -80,11 +91,24 @@ const _crawlModelInfo = async (modelName: string): Promise => { const modelInfo = JSON.parse(decodedStr); const modelId = modelInfo?.model?.id; - const modelTask = modelInfo?.model?.pipeline_tag; + let modelTask = modelInfo?.model?.pipeline_tag; // Make sure we have the required info if (!modelId || !modelTask) return null; + // Resolve the effective task using inference provider mappings. + // The crawled data may include the mapping; if not, fetch it from the API for text-generation models. + let providerMapping = modelInfo?.model?.inferenceProviderMapping; + if (!providerMapping && modelTask === 'text-generation') { + try { + const apiModel = await _fetchModel(modelName); + providerMapping = apiModel?.inferenceProviderMapping; + } catch { + // If API call fails, keep the crawled task + } + } + modelTask = _resolveEffectiveTask(modelTask, providerMapping); + const inference = modelInfo?.model?.inference; let logoUrl = modelInfo?.author?.avatarUrl; @@ -114,13 +138,38 @@ const _crawlModelInfo = async (modelName: string): Promise => { const _fetchModel = async (modelName: string) => { try { - const res = await axios.get(`https://huggingface.co/api/models/${modelName}`); + const res = await hfAxios.get(`https://huggingface.co/api/models/${modelName}`, { + params: { 'expand[]': 'inferenceProviderMapping' }, + }); return res?.data; } catch (error) { throw { message: error?.response?.data?.error || `Hugging Face Model not found!` }; } }; +/** + * Resolve the effective task by checking inference provider mappings. + * Modern LLMs often have pipeline_tag "text-generation" but inference providers + * only support "conversational" (chatCompletion). This detects the correct task. + */ +const _resolveEffectiveTask = (pipelineTag: string, inferenceProviderMapping: any): string => { + if (!pipelineTag || !inferenceProviderMapping) return pipelineTag; + + const mappings = Array.isArray(inferenceProviderMapping) + ? inferenceProviderMapping + : Object.entries(inferenceProviderMapping).map( + ([provider, mapping]: [string, any]) => ({ provider, task: mapping.task }), + ); + + if (mappings.length === 0) return pipelineTag; + + const exactMatch = mappings.find((m: any) => m.task === pipelineTag); + if (exactMatch) return pipelineTag; + + const resolvedTask = mappings[0]?.task; + return resolvedTask && supportedHfTasks.includes(resolvedTask) ? resolvedTask : pipelineTag; +}; + /** * If the crawling approach fails, then fallback to this approach * @param {string} modelName @@ -132,7 +181,7 @@ const _fallbackModelInfo = async (modelName: string): Promise => { const id = model?.id; const modelId = model?.modelId; - const modelTask = model?.pipeline_tag; + const modelTask = _resolveEffectiveTask(model?.pipeline_tag, model?.inferenceProviderMapping); const inference = model?.cardData?.inference; const logoUrl = await _getModelLogo(modelName); @@ -179,7 +228,7 @@ const _fetchModels = async ({ if (cursor) params['cursor'] = cursor; - const result = await axios.get(url, { params }); + const result = await hfAxios.get(url, { params }); const cursors = getCursorFromLinkHeader(result?.headers?.link); @@ -422,8 +471,9 @@ const _filterModels: FilterModels = async ({ retry = 0, search = '', cursors, pa export async function getModelInfo(modelName: string): Promise { try { const model = await _fetchModel(modelName); + const effectiveTask = _resolveEffectiveTask(model?.pipeline_tag, model?.inferenceProviderMapping); - const modelInfo = await _getModelInfo(modelName, model?.pipeline_tag); + const modelInfo = await _getModelInfo(modelName, effectiveTask); return { success: true, data: modelInfo }; } catch (error) { diff --git a/packages/app/src/builder-ui/components/HuggingFace.class.ts b/packages/app/src/builder-ui/components/HuggingFace.class.ts index 6372460bb..b0f958e1e 100644 --- a/packages/app/src/builder-ui/components/HuggingFace.class.ts +++ b/packages/app/src/builder-ui/components/HuggingFace.class.ts @@ -1,11 +1,11 @@ -import { Component } from './Component.class'; import hfParams from '../params/hugging-face.params.json'; import { - kebabToCapitalize, handleKvFieldEditBtn, - setLogoForDynamicComp, + kebabToCapitalize, promptVaultInfo, + setLogoForDynamicComp, } from '../utils'; +import { Component } from './Component.class'; declare var Metro; From db42f435220fd42bc748f55a697088fe6cf04f16 Mon Sep 17 00:00:00 2001 From: Forhad Hosain Date: Thu, 2 Apr 2026 12:53:34 +0600 Subject: [PATCH 4/5] explain why we have hfAxios with 2000ms timeout --- .../src/backend/services/huggingFace.service.ts | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/packages/app/src/backend/services/huggingFace.service.ts b/packages/app/src/backend/services/huggingFace.service.ts index 9c54b22e3..9b98ae01d 100644 --- a/packages/app/src/backend/services/huggingFace.service.ts +++ b/packages/app/src/backend/services/huggingFace.service.ts @@ -11,9 +11,19 @@ import * as openai from './openai-helper'; import Cache from './Cache.class'; import Store from './Store.class'; -// Increase the Happy Eyeballs (autoSelectFamily) timeout from the default 250ms to 2000ms. -// On networks with broken IPv6, the default 250ms is too short for the IPv4 fallback to -// connect before the failed IPv6 attempt aborts the whole connection. +// Node.js 20+ enables the Happy Eyeballs algorithm (autoSelectFamily) by default, which +// attempts IPv6 and IPv4 connections in parallel. The default fallback timeout is 250ms, +// which can be too short on networks with broken or slow IPv6 — the IPv4 fallback doesn't +// get enough time to connect before the whole attempt is aborted (ETIMEDOUT). +// +// We increase autoSelectFamilyAttemptTimeout to 2000ms to give the IPv4 fallback enough +// time to establish a connection when IPv6 fails. +// +// Troubleshooting: If HuggingFace requests still time out locally, try increasing the +// value (e.g. 2000, 5000). To diagnose, run in terminal: +// curl -4 --connect-timeout 5 https://huggingface.co/api/models?limit=1 +// If curl works but Node.js doesn't, the issue is Happy Eyeballs — increase the timeout. +// If curl also fails, it's a network/firewall issue unrelated to this setting. const hfAxios = axios.create({ timeout: 30000, httpAgent: new http.Agent({ keepAlive: true, autoSelectFamilyAttemptTimeout: 2000 }), From d6756984c4aaf404cb8a38b1bc898ddc192e5d87 Mon Sep 17 00:00:00 2001 From: Forhad Hosain Date: Thu, 2 Apr 2026 16:18:52 +0600 Subject: [PATCH 5/5] fix: add Hugging Face model manually --- .../routes/api/component/HuggingFace.ts | 80 ++++++++++--------- .../backend/services/huggingFace.service.ts | 23 +++--- packages/app/src/builder-ui/ui/dialogs.ts | 32 +++++--- 3 files changed, 76 insertions(+), 59 deletions(-) diff --git a/packages/app/src/backend/routes/api/component/HuggingFace.ts b/packages/app/src/backend/routes/api/component/HuggingFace.ts index eed017dd3..79e5efdb7 100644 --- a/packages/app/src/backend/routes/api/component/HuggingFace.ts +++ b/packages/app/src/backend/routes/api/component/HuggingFace.ts @@ -11,56 +11,60 @@ const router = express.Router(); const HUGGING_FACE_MODELS_SETTINGS_KEY = 'HuggingFaceModels'; router.post('/', async (req: Request, res: Response) => { - let { data = null } = req.body; + try { + let { data = null } = req.body; - const modelName = data?.resourceKey; + const modelName = data?.resourceKey; - if (modelName) { - const modelRes = await getModelInfo(modelName); + if (modelName) { + const modelRes = await getModelInfo(modelName); - if (!modelRes?.success) { - return res.status(400).json({ success: false, error: modelRes?.error }); + if (!modelRes?.success) { + return res.status(400).json({ success: false, error: modelRes?.error }); + } + + data = modelRes?.data; } - data = modelRes?.data; - } + if (!data?.name) { + return res.status(400).json({ success: false, error: `Model not found!` }); + } - if (!data?.name) { - return res.status(400).json({ success: false, error: `Model not found!` }); - } + if (!data?.inference) { + return res + .status(400) + .json({ success: false, error: `Currently, we support models with Hosted Inference API.` }); + } - if (!data?.inference) { - return res - .status(400) - .json({ success: false, error: `Currently, we support models with Hosted Inference API.` }); - } + if (!data?.modelTask) { + return res + .status(400) + .json({ success: false, error: `Currently, we support models with "task"` }); + } - if (!data?.modelTask) { - return res - .status(400) - .json({ success: false, error: `Currently, we support models with "task"` }); - } + if (!supportedHfTasks.includes(data?.modelTask)) { + return res.status(400).json({ + success: false, + error: `Currently, Models under "${kebabToCapitalize( + data?.modelTask, + )}" task is not supported`, + }); + } - if (!supportedHfTasks.includes(data?.modelTask)) { - return res.status(400).json({ - success: false, - error: `Currently, Models under "${kebabToCapitalize( - data?.modelTask, - )}" task is not supported`, - }); - } + const settingsRes = await userData.saveUserSettings( + req?.user?.accessToken, + HUGGING_FACE_MODELS_SETTINGS_KEY, + data, + ); - const settingsRes = await userData.saveUserSettings( - req?.user?.accessToken, - HUGGING_FACE_MODELS_SETTINGS_KEY, - data, - ); + if (!settingsRes?.success) { + return res.status(400).json({ success: false, error: settingsRes?.error }); + } - if (!settingsRes?.success) { - return res.status(400).json({ success: false, error: settingsRes?.error }); + res.send({ success: true, data }); + } catch (error) { + return res.status(500).json({ success: false, error: error?.message || 'Something went wrong!' }); } - - res.send({ success: true, data }); }); router.get('/', async (req, res) => { diff --git a/packages/app/src/backend/services/huggingFace.service.ts b/packages/app/src/backend/services/huggingFace.service.ts index 9b98ae01d..aee5e7097 100644 --- a/packages/app/src/backend/services/huggingFace.service.ts +++ b/packages/app/src/backend/services/huggingFace.service.ts @@ -97,6 +97,7 @@ const _crawlModelInfo = async (modelName: string): Promise => { const dataElm = $('main > .SVELTE_HYDRATER.contents'); const data = dataElm.attr('data-props'); + if (!data) return null; const decodedStr = he.decode(data); const modelInfo = JSON.parse(decodedStr); @@ -250,22 +251,22 @@ const _fetchModels = async ({ const _getModelInfo = async (modelName: string, modelTask: string): Promise => { try { - let modelsInfo = await modelInfoCache.get(modelTask); - modelsInfo = modelsInfo?.data; + if (modelTask) { + let modelsInfo = await modelInfoCache.get(modelTask); + modelsInfo = modelsInfo?.data; - let modelInfo = {}; + // If we have the model info in cache, then return it + if (isValidObj(modelsInfo)) { + const cachedInfo = modelsInfo?.[modelName]; - // If we have the model info in cache, then return it - if (isValidObj(modelsInfo)) { - modelInfo = modelsInfo?.[modelName]; - - if (isValidObj(modelInfo)) { - return modelInfo; + if (isValidObj(cachedInfo)) { + return cachedInfo; + } } } // If we don't have the model info in cache, then crawl it - modelInfo = await _crawlModelInfo(modelName); + let modelInfo = await _crawlModelInfo(modelName); // If crawling fails, then fallback to the API approach if (!modelInfo) { @@ -273,7 +274,7 @@ const _getModelInfo = async (modelName: string, modelTask: string): Promise