How to Integrate Custom AI Models with AiToEarn: A Complete Developer Guide
You can integrate custom AI models into AiToEarn by defining model parameters in the backend configuration DTOs, exposing them through the generic AiService endpoints, and consuming them via the frontend API wrappers in src/api/ai.ts without modifying any UI components.
AiToEarn uses a modular architecture that separates model definition, backend service exposure, and frontend consumption to streamline AI monetization workflows. Integrating custom large language models (LLMs), image generators, or video synthesis engines requires updating the NestJS backend configuration and ensuring the Next.js frontend recognizes the new capabilities through existing API contracts.
Architecture Overview
The integration follows a three-tier flow that keeps UI changes minimal while maximizing backend flexibility:
- Model Definition – Declare the model’s capabilities, parameters, and metadata in TypeScript interfaces and DTOs stored in the
models-configmodule. - Service Exposure – The
AiServiceclass reads these definitions from internal endpoints (/internal/ai/models/*) and routes generation requests to the appropriate provider. - Client Consumption – The frontend fetches available models via the public API wrappers in
project/aitoearn-web/src/api/ai.tsand dynamically populates selection dropdowns based on the returned configuration.
Step 1 – Define the Custom Model Configuration
Add your custom model to the backend by extending the appropriate value object (VO) or DTO. The system supports chat completions, image generation, and video generation through distinct interfaces.
Configuring Chat Models
Update the interface in ai.interface.ts to include your model’s specifications:
// project/aitoearn-backend/libs/aitoearn-ai-client/src/interfaces/ai.interface.ts
export interface ChatModelConfigVo {
name: string; // Unique identifier used in API calls
displayName: string; // Human-readable label for UI
maxTokens: number;
temperature: number;
// Add custom fields as needed for your provider
}
Then register the model in the configuration DTO:
// project/aitoearn-backend/apps/aitoearn-ai/src/core/ai/models-config/models-config.dto.ts
export class ModelsConfigDto {
chatModels: ChatModelConfigVo[] = [
{
name: 'gpt-custom-v1',
displayName: 'GPT Custom v1',
maxTokens: 8192,
temperature: 0.7,
},
];
}
Configuring Image and Video Models
For diffusion or video models, extend ImageGenerationModelParamsVo or VideoGenerationModelParamsVo:
// Example for a custom Stable Diffusion endpoint
export const customImageModels: ImageGenerationModelParamsVo[] = [
{
name: 'stable-diffusion-custom',
displayName: 'My Custom SD',
sizeOptions: ['512x512', '1024x1024'],
// Provider-specific parameters
},
];
Step 2 – Expose the Model via the Backend Service
The AiService class handles all communication with the internal AI engine. It automatically exposes any models defined in the configuration DTO through dedicated getter methods.
Internal Endpoint Exposure
The service retrieves chat models using a POST request to the internal router:
// In AiService (project/aitoearn-backend/libs/aitoearn-ai-client/src/clients/ai.service.ts)
async getChatModels(data: { userId?: string; userType?: UserType }) {
const url = `/internal/ai/models/chat`;
const config: AxiosRequestConfig = { method: 'POST', data };
return this.request<ChatModelConfigVo[]>(url, config);
}
Similar methods exist for image and video models (getImageGenerationModels and getVideoGenerationModels). Because these methods read directly from the configuration DTO, your custom model appears in the API response immediately after you update the DTO and restart the service.
Routing Generation Requests
When the frontend triggers generation, the backend forwards the request to the custom model’s endpoint using the model parameter from the payload:
async videoGeneration<T>(data: VideoGenerationModelParamsVo) {
const url = `/internal/ai/generate/video`;
// The 'model' field in data determines the target provider
return this.request<T>(url, { method: 'POST', data });
}
Step 3 – Consume the Model in the Frontend
The web client fetches the model list and renders selectors without hardcoded model names, enabling seamless integration of custom backends.
Fetching Available Models
Import the API wrappers from the ai module:
// project/aitoearn-web/src/api/ai.ts
import {
getChatModels,
getImageGenerationModels,
getVideoGenerationModels
} from '@/api/ai';
async function loadModelOptions() {
const [chatModels, imageModels, videoModels] = await Promise.all([
getChatModels(),
getImageGenerationModels(),
getVideoGenerationModels(),
]);
// Populate state for dropdown components
return {
chat: chatModels.data,
image: imageModels.data,
video: videoModels.data,
};
}
Triggering Generation with Custom Models
Pass the selected model name to the generation function exactly as it appears in the configuration:
import { generateImage } from '@/api/ai';
async function createCustomImage(prompt: string, modelName: string) {
// modelName must match the 'name' field from ImageGenerationModelParamsVo
const response = await generateImage({
prompt,
model: modelName, // e.g., 'stable-diffusion-custom'
size: '512x512',
});
return response.data;
}
The generateImage function (lines 24‑35) POSTs to /api/ai/generate/image, which the backend routes to your custom provider based on the model parameter.
End-to-End Integration Example
Below is a complete workflow adding a custom image generation model:
// 1. Backend – Define the model (ai.interface.ts)
export interface ImageGenerationModelParamsVo {
name: string; // 'my-custom-model'
displayName: string; // 'My Custom AI'
sizeOptions: string[]; // ['256x256', '512x512']
}
// 2. Backend – Add to config DTO (models-config.dto.ts)
export const modelConfig = {
imageModels: [
{ name: 'my-custom-model', displayName: 'My Custom AI', sizeOptions: ['512x512'] }
]
};
// 3. Frontend – Fetch and use (React component)
import { useEffect, useState } from 'react';
import { getImageGenerationModels, generateImage } from '@/api/ai';
export function ImageGenerator() {
const [models, setModels] = useState<ImageGenerationModelParamsVo[]>([]);
useEffect(() => {
getImageGenerationModels().then(res => setModels(res.data));
}, []);
const handleGenerate = async (prompt: string, modelName: string) => {
const result = await generateImage({ prompt, model: modelName });
console.log(result.url);
};
return (
<select>
{models.map(m => (
<option key={m.name} value={m.name}>{m.displayName}</option>
))}
</select>
);
}
Key Files Reference
| File | Purpose | GitHub Link |
|---|---|---|
src/api/ai.ts |
Frontend API wrappers for fetching models and triggering generation | src/api/ai.ts |
ai.service.ts |
Backend client that calls internal AI endpoints and returns model configurations | libs/aitoearn-ai-client/src/clients/ai.service.ts |
ai.interface.ts |
TypeScript definitions for chat, image, and video model parameters | libs/aitoearn-ai-client/src/interfaces/ai.interface.ts |
models-config.dto.ts |
DTO that validates and transports model-config payloads | apps/aitoearn-ai/src/core/ai/models-config/models-config.dto.ts |
AiBatchGenerateBar/constants.ts |
UI component constants that build the model-selection interface | draft-box/AiBatchGenerateBar/constants.ts |
Summary
- Define your custom model by adding entries to
ChatModelConfigVo,ImageGenerationModelParamsVo, orVideoGenerationModelParamsVoin the backend interfaces and DTOs. - Expose the model automatically through
AiService.getChatModels(),getImageGenerationModels(), orgetVideoGenerationModels(), which read from the configuration DTO and serve internal endpoints. - Consume the model in the frontend by calling
getChatModels(),getImageGenerationModels(), orgetVideoGenerationModels()fromsrc/api/ai.ts, then passing the selectednameto the respective generation function. - Match exactly the model identifier between backend configuration and frontend API calls to ensure proper routing.
Frequently Asked Questions
Do I need to modify the frontend code to add a new custom model?
No. The frontend dynamically renders model dropdowns based on the data returned by getChatModels, getImageGenerationModels, and getVideoGenerationModels. As long as your backend DTO includes the new model, it will appear in the UI automatically without touching React components.
What parameters are required when defining an image generation model?
According to the ImageGenerationModelParamsVo interface in [ai.interface.ts](https://github.com/yikart/AiToEarn/blob/main/project/aitoearn-backend/libs/aitoearn-ai-client/src/interfaces/ai.interface.ts), you must provide at minimum a name (unique identifier), displayName (UI label), and sizeOptions (array of supported resolutions). Additional provider-specific fields can be added to the interface as optional properties.
How does the backend route requests to the correct custom model endpoint?
The backend AiService forwards the model parameter from the request payload (e.g., the model field in VideoGenerationModelParamsVo) to the internal AI engine. The engine matches this identifier against the configuration DTO to determine which provider endpoint should handle the generation, requiring no code changes in the service logic when adding new models.
Can I add multiple custom models simultaneously?
Yes. The ModelsConfigDto accepts arrays for each model type (chatModels, imageModels, videoModels). You can seed the database or populate the DTO with multiple entries, and all will be exposed through the same get*Models endpoints immediately upon deployment.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →