Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions docs/content/docs/reference/components/nano-gpt_v1.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,21 @@ Version: 1



## Connection Setup

1. Navigate to [NanoGPT console](https://nano-gpt.com/conversation/new).
2. Click on **API**.
3. Click on **Create API Key**.
4. Enter name of your new key.
5. Click on **Create**.
6. Here is your new API key.
7. Done 🚀.

<div style={{ position: 'relative', height:0, width: '100%', overflow: 'hidden', zIndex: 49, boxSizing: 'border-box', paddingBottom: 'calc(50.05219207% + 32px)'}}>
<iframe src="https://www.guidejar.com/embed/0ea7b852-b858-46d1-96fc-9654603332b4?type=1&controls=on" width="100%" height="100%" style={{height:'100%', position:'absolute', inset:0, border: 'none'}} allowFullScreen></iframe>
</div>





Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,22 @@
*/
public class NanoGptCreateSpeechAction {

private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
private static final int MAX_POLL_ATTEMPTS = 40;
private static final int POLL_INTERVAL_MS = 3000;
protected static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
protected static final int MAX_POLL_ATTEMPTS = 40;
protected static final int POLL_INTERVAL_MS = 3000;

private record AudioFetchResult(byte[] bytes, String extension, String audioUrl) {
protected record AudioFetchResult(byte[] bytes, String extension, String audioUrl) {

protected AudioFetchResult(byte[] bytes, String extension, String audioUrl) {
this.bytes = bytes == null ? null : bytes.clone();
this.extension = extension;
this.audioUrl = audioUrl;
}

@Override
public byte[] bytes() {
return bytes == null ? null : bytes.clone();
}
}

public static final ModifiableActionDefinition ACTION_DEFINITION = action(CREATE_SPEECH)
Expand Down Expand Up @@ -111,12 +122,12 @@ public static Object perform(Parameters inputParameters, Parameters connectionPa
Map<String, Object> requestBody = new HashMap<>();

requestBody.put("text", inputParameters.getRequiredString(INPUT));
requestBody.put("model", inputParameters.getRequiredString(MODEL));
requestBody.put(MODEL, inputParameters.getRequiredString(MODEL));

String voice = inputParameters.getString(VOICE);

if (voice != null && !voice.isBlank()) {
requestBody.put("voice", voice);
requestBody.put(VOICE, voice);
}

String responseFormat = inputParameters.getString(RESPONSE_FORMAT, "mp3");
Expand All @@ -126,7 +137,7 @@ public static Object perform(Parameters inputParameters, Parameters connectionPa
Double speed = inputParameters.getDouble(SPEED);

if (speed != null) {
requestBody.put("speed", speed);
requestBody.put(SPEED, speed);
}

RestClient restClient = ModelUtils.getRestClientBuilder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ public class NanoGptCreateTranscriptionAction {
TRANSCRIPTION_MODEL_PROPERTY,
fileEntry(FILE)
.label("File")
.description(
"The audio file to transcribe. Supported formats: MP3, WAV, M4A, OGG, AAC (max 3MB).")
.description("The audio file to transcribe. Supported formats: MP3, WAV, M4A, OGG, AAC (max 3MB).")
.required(true),
TRANSCRIPTION_LANGUAGE_PROPERTY)
.output(outputSchema(string()))
Expand All @@ -80,12 +79,12 @@ public String getFilename() {
}
});

formData.add("model", inputParameters.getRequiredString(MODEL));
formData.add(MODEL, inputParameters.getRequiredString(MODEL));

String language = inputParameters.getString(LANGUAGE);

if (language != null) {
formData.add("language", language);
formData.add(LANGUAGE, language);
}

RestClient restClient = ModelUtils.getRestClientBuilder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@
public final class NanoGptConnection {

public static final ModifiableConnectionDefinition CONNECTION_DEFINITION =
RouterConnection.connectionDefinition(BASE_URL);
RouterConnection.connectionDefinition(BASE_URL)
.version(1)
.help("", "https://docs.bytechef.io/reference/components/nano-gpt_v1#connection-setup");

private NanoGptConnection() {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,42 @@ protected void addProviderSpecificParams(Map<String, Object> body) {
}
}

public Double getMinP() {
return minP;
}

public Integer getMinTokens() {
return minTokens;
}

public Integer getMirostatMode() {
return mirostatMode;
}

public Double getMirostatTau() {
return mirostatTau;
}

public Double getMirostatEta() {
return mirostatEta;
}

public Double getRepetitionPenalty() {
return repetitionPenalty;
}

public Double getTfs() {
return tfs;
}

public Double getTopA() {
return topA;
}

public Double getTypicalP() {
return typicalP;
}

public static class Builder extends RouterChatModel.Builder<Builder> {

private Double minP;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,42 @@ public class NanoGptImageModel implements ImageModel {
private final Double strength;
private final Integer numInferenceSteps;

public String getModel() {
return model;
}

public String getSize() {
return size;
}

public String getResponseFormat() {
return responseFormat;
}

public String getUser() {
return user;
}

public Integer getN() {
return n;
}

public Integer getSeed() {
return seed;
}

public Double getGuidanceScale() {
return guidanceScale;
}

public Double getStrength() {
return strength;
}

public Integer getNumInferenceSteps() {
return numInferenceSteps;
}

private NanoGptImageModel(Builder builder) {
this.restClient = ModelUtils.getRestClientBuilder()
.defaultHeader(HttpHeaders.AUTHORIZATION, "Bearer " + builder.apiKey)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## Connection Setup

1. Navigate to [NanoGPT console](https://nano-gpt.com/conversation/new).
2. Click on **API**.
3. Click on **Create API Key**.
4. Enter name of your new key.
5. Click on **Create**.
6. Here is your new API key.
7. Done 🚀.

<div style={{ position: 'relative', height:0, width: '100%', overflow: 'hidden', zIndex: 49, boxSizing: 'border-box', paddingBottom: 'calc(50.05219207% + 32px)'}}>
<iframe src="https://www.guidejar.com/embed/0ea7b852-b858-46d1-96fc-9654603332b4?type=1&controls=on" width="100%" height="100%" style={{height:'100%', position:'absolute', inset:0, border: 'none'}} allowFullScreen></iframe>
</div>


Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright 2025 ByteChef
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.bytechef.component.ai.llm.router.nano.gpt.action;

import static com.bytechef.component.ai.llm.constant.LLMConstants.FREQUENCY_PENALTY;
import static com.bytechef.component.ai.llm.constant.LLMConstants.LOGIT_BIAS;
import static com.bytechef.component.ai.llm.constant.LLMConstants.MAX_TOKENS;
import static com.bytechef.component.ai.llm.constant.LLMConstants.MODEL;
import static com.bytechef.component.ai.llm.constant.LLMConstants.PRESENCE_PENALTY;
import static com.bytechef.component.ai.llm.constant.LLMConstants.REASONING;
import static com.bytechef.component.ai.llm.constant.LLMConstants.SEED;
import static com.bytechef.component.ai.llm.constant.LLMConstants.STOP;
import static com.bytechef.component.ai.llm.constant.LLMConstants.TEMPERATURE;
import static com.bytechef.component.ai.llm.constant.LLMConstants.TOP_K;
import static com.bytechef.component.ai.llm.constant.LLMConstants.TOP_P;
import static com.bytechef.component.ai.llm.constant.LLMConstants.USER;
import static com.bytechef.component.ai.llm.constant.LLMConstants.VERBOSITY;
import static com.bytechef.component.ai.llm.router.constant.RouterConstants.LOGPROBS;
import static com.bytechef.component.ai.llm.router.constant.RouterConstants.MAX_COMPLETION_TOKENS;
import static com.bytechef.component.ai.llm.router.constant.RouterConstants.TOP_LOGPROBS;
import static com.bytechef.component.ai.llm.router.nano.gpt.constant.NanoGptConstants.MIN_P;
import static com.bytechef.component.ai.llm.router.nano.gpt.constant.NanoGptConstants.MIN_TOKENS;
import static com.bytechef.component.ai.llm.router.nano.gpt.constant.NanoGptConstants.MIROSTAT_ETA;
import static com.bytechef.component.ai.llm.router.nano.gpt.constant.NanoGptConstants.MIROSTAT_MODE;
import static com.bytechef.component.ai.llm.router.nano.gpt.constant.NanoGptConstants.MIROSTAT_TAU;
import static com.bytechef.component.ai.llm.router.nano.gpt.constant.NanoGptConstants.REPETITION_PENALTY;
import static com.bytechef.component.ai.llm.router.nano.gpt.constant.NanoGptConstants.TFS;
import static com.bytechef.component.ai.llm.router.nano.gpt.constant.NanoGptConstants.TOP_A;
import static com.bytechef.component.ai.llm.router.nano.gpt.constant.NanoGptConstants.TYPICAL_P;
import static com.bytechef.component.definition.Authorization.TOKEN;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import com.bytechef.component.ai.llm.router.nano.gpt.model.NanoGptChatModel;
import com.bytechef.component.definition.Parameters;
import com.bytechef.component.test.definition.MockParametersFactory;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Test;

/**
* @author Nikolina Spehar
*/
class NanoGptChatActionTest {

private final Parameters mockedParameters = MockParametersFactory.create(
Map.ofEntries(
Map.entry(TOKEN, "token"), Map.entry(MODEL, "model"),
Map.entry(FREQUENCY_PENALTY, 1.0), Map.entry(LOGIT_BIAS, Map.of()),
Map.entry(LOGPROBS, false), Map.entry(MAX_COMPLETION_TOKENS, 1),
Map.entry(MAX_TOKENS, 1), Map.entry(PRESENCE_PENALTY, 0.0),
Map.entry(REASONING, "reasoning"), Map.entry(SEED, 4),
Map.entry(STOP, List.of()), Map.entry(TEMPERATURE, 0.0),
Map.entry(TOP_K, 0.0), Map.entry(TOP_LOGPROBS, 1), Map.entry(TOP_P, 0.0),
Map.entry(VERBOSITY, "verbosity"), Map.entry(USER, "user"),
Map.entry(MIN_P, 0.0), Map.entry(MIN_TOKENS, 1), Map.entry(MIROSTAT_MODE, 1),
Map.entry(MIROSTAT_TAU, 0.0), Map.entry(MIROSTAT_ETA, 0.0), Map.entry(REPETITION_PENALTY, 0.0),
Map.entry(TFS, 0.0), Map.entry(TOP_A, 0.0), Map.entry(TYPICAL_P, 0.0)));

@Test
void testPerform() {

Check warning on line 75 in server/libs/modules/components/ai/llm/router/nano-gpt/src/test/java/com/bytechef/component/ai/llm/router/nano/gpt/action/NanoGptChatActionTest.java

View check run for this annotation

SonarQubeCloud / [server] SonarCloud Code Analysis

Refactor this method to reduce the number of assertions from 26 to less than 25.

See more on https://sonarcloud.io/project/issues?id=bytechef_server&issues=AZ6N3h7aUbyiFX7CznVU&open=AZ6N3h7aUbyiFX7CznVU&pullRequest=5140
NanoGptChatModel nanoGptChatModel = (NanoGptChatModel) NanoGptChatAction.CHAT_MODEL.createChatModel(
mockedParameters, mockedParameters, false);

assertNotNull(nanoGptChatModel);

assertEquals("model", nanoGptChatModel.getModel());
assertEquals(1.0, nanoGptChatModel.getFrequencyPenalty());
assertEquals(Map.of(), nanoGptChatModel.getLogitBias());
assertEquals(false, nanoGptChatModel.getLogprobs());
assertEquals(1, nanoGptChatModel.getMaxCompletionTokens());
assertEquals(1, nanoGptChatModel.getMaxTokens());
assertEquals(0.0, nanoGptChatModel.getPresencePenalty());
assertEquals("reasoning", nanoGptChatModel.getReasoning());
assertEquals(4, nanoGptChatModel.getSeed());
assertEquals(List.of(), nanoGptChatModel.getStop());
assertEquals(0.0, nanoGptChatModel.getTemperature());
assertEquals(0.0, nanoGptChatModel.getTopK());
assertEquals(1, nanoGptChatModel.getTopLogprobs());
assertEquals(0.0, nanoGptChatModel.getTopP());
assertEquals("verbosity", nanoGptChatModel.getVerbosity());
assertEquals("user", nanoGptChatModel.getUser());
assertEquals(0.0, nanoGptChatModel.getMinP());
assertEquals(1, nanoGptChatModel.getMinTokens());
assertEquals(1, nanoGptChatModel.getMirostatMode());
assertEquals(0.0, nanoGptChatModel.getMirostatTau());
assertEquals(0.0, nanoGptChatModel.getMirostatEta());
assertEquals(0.0, nanoGptChatModel.getRepetitionPenalty());
assertEquals(0.0, nanoGptChatModel.getTfs());
assertEquals(0.0, nanoGptChatModel.getTopA());
assertEquals(0.0, nanoGptChatModel.getTypicalP());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright 2025 ByteChef
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.bytechef.component.ai.llm.router.nano.gpt.action;

import static com.bytechef.component.ai.llm.constant.LLMConstants.MODEL;
import static com.bytechef.component.ai.llm.constant.LLMConstants.N;
import static com.bytechef.component.ai.llm.constant.LLMConstants.RESPONSE_FORMAT;
import static com.bytechef.component.ai.llm.constant.LLMConstants.SEED;
import static com.bytechef.component.ai.llm.constant.LLMConstants.SIZE;
import static com.bytechef.component.ai.llm.constant.LLMConstants.USER;
import static com.bytechef.component.ai.llm.router.nano.gpt.constant.NanoGptConstants.GUIDANCE_SCALE;
import static com.bytechef.component.ai.llm.router.nano.gpt.constant.NanoGptConstants.NUM_INFERENCE_STEPS;
import static com.bytechef.component.ai.llm.router.nano.gpt.constant.NanoGptConstants.STRENGTH;
import static com.bytechef.component.definition.Authorization.TOKEN;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import com.bytechef.component.ai.llm.router.nano.gpt.model.NanoGptImageModel;
import com.bytechef.component.definition.Parameters;
import com.bytechef.component.test.definition.MockParametersFactory;
import java.util.Map;
import org.junit.jupiter.api.Test;

/**
* @author Nikolina Spehar
*/
class NanoGptCreateImageActionTest {

private final Parameters mockedParameters = MockParametersFactory.create(
Map.ofEntries(Map.entry(MODEL, "model"), Map.entry(SIZE, "1024x1024"),
Map.entry(RESPONSE_FORMAT, "url"), Map.entry(N, 1), Map.entry(SEED, 1),
Map.entry(GUIDANCE_SCALE, 0.0), Map.entry(USER, "user"), Map.entry(STRENGTH, 0.0),
Map.entry(NUM_INFERENCE_STEPS, 1)));

private final Parameters mockedConnectionParameters = MockParametersFactory.create(Map.of(TOKEN, "token"));

@Test
void testCreateImageModel() {
NanoGptImageModel nanoGptImageModel = (NanoGptImageModel) NanoGptCreateImageAction.IMAGE_MODEL.createImageModel(
mockedParameters, mockedConnectionParameters);

assertNotNull(nanoGptImageModel);

assertEquals("model", nanoGptImageModel.getModel());
assertEquals("1024x1024", nanoGptImageModel.getSize());
assertEquals("url", nanoGptImageModel.getResponseFormat());
assertEquals(1, nanoGptImageModel.getN());
assertEquals(1, nanoGptImageModel.getSeed());
assertEquals(0.0, nanoGptImageModel.getGuidanceScale());
assertEquals(0.0, nanoGptImageModel.getStrength());
assertEquals(1, nanoGptImageModel.getNumInferenceSteps());
assertEquals("user", nanoGptImageModel.getUser());
}
}
Loading
Loading