Skip to content
Merged
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
10 changes: 10 additions & 0 deletions examples/nodejs/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,13 @@ LANGBASE_API_KEY=""
EXA_API_KEY=""
CRAWL_KEY=""
FIRECRAWL_KEY=""

# Image generation API keys
# https://platform.openai.com/api-keys
OPENAI_API_KEY=""
# https://console.cloud.google.com/apis/credentials
GOOGLE_API_KEY=""
# https://api.together.xyz/settings/api-keys
TOGETHER_API_KEY=""
# https://openrouter.ai/keys
OPENROUTER_API_KEY=""
36 changes: 36 additions & 0 deletions examples/nodejs/images/google.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import 'dotenv/config';
import {Langbase} from 'langbase';

async function main() {
// Check if API keys are available
if (!process.env.LANGBASE_API_KEY) {
console.error('❌ LANGBASE_API_KEY is not set in environment variables');
return;
}

if (!process.env.GOOGLE_API_KEY) {
console.error('❌ GOOGLE_API_KEY is not set in environment variables');
console.log('Please add your Google API key to the .env file');
return;
}

const langbase = new Langbase({
apiKey: process.env.LANGBASE_API_KEY!
});

try {
const result = await langbase.images.generate({
prompt: "A futuristic cityscape with flying cars and neon lights, cyberpunk style, highly detailed, 8k resolution",
model: "google:gemini-2.5-flash-image-preview",
apiKey: process.env.GOOGLE_API_KEY!
});

console.log('✅ Image generated successfully!');
console.log('Generated images:', result);

} catch (error) {
console.error('❌ Error generating image:', error);
}
}

main();
36 changes: 36 additions & 0 deletions examples/nodejs/images/openai.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import 'dotenv/config';
import {Langbase} from '../../../packages/langbase/src/langbase/langbase';

async function main() {
// Check if API keys are available
if (!process.env.LANGBASE_API_KEY) {
console.error('❌ LANGBASE_API_KEY is not set in environment variables');
return;
}

if (!process.env.OPENAI_API_KEY) {
console.error('❌ OPENAI_API_KEY is not set in environment variables');
console.log('Please add your OpenAI API key to the .env file');
return;
}

const langbase = new Langbase({
apiKey: process.env.LANGBASE_API_KEY!
});

try {
const result = await langbase.images.generate({
prompt: "A futuristic cityscape with flying cars and neon lights, cyberpunk style, highly detailed, 8k resolution",
model: "openai:gpt-image-1",
apiKey: process.env.OPENAI_API_KEY!
});

console.log('✅ Image generated successfully!');
console.log('Generated images:', result);

} catch (error) {
console.error('❌ Error generating image:', error);
}
}

main();
37 changes: 37 additions & 0 deletions examples/nodejs/images/openrouter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import 'dotenv/config';
import {Langbase} from 'langbase';

async function main() {
// Check if API keys are available
if (!process.env.LANGBASE_API_KEY) {
console.error('❌ LANGBASE_API_KEY is not set in environment variables');
return;
}

if (!process.env.OPENROUTER_API_KEY) {
console.error('❌ OPENROUTER_API_KEY is not set in environment variables');
console.log('Please add your OpenRouter API key to the .env file');
return;
}

const langbase = new Langbase({
apiKey: process.env.LANGBASE_API_KEY!,
});

try {
const result = await langbase.images.generate({
prompt: "A majestic dragon soaring through clouds above a fantasy castle, epic fantasy art style, detailed scales and wings",
model: "openrouter:google/gemini-2.5-flash-image-preview",
apiKey: process.env.OPENROUTER_API_KEY
});

console.log('✅ Image generated successfully via OpenRouter!');
console.log('Generated images:', result);

} catch (error) {
console.error('❌ Error generating image:', error);
console.log('Note: Make sure you have a valid OpenRouter API key and credits');
}
}

main();
42 changes: 42 additions & 0 deletions examples/nodejs/images/together.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import 'dotenv/config';
import {Langbase} from 'langbase';

async function main() {
// Check if API keys are available
if (!process.env.LANGBASE_API_KEY) {
console.error('❌ LANGBASE_API_KEY is not set in environment variables');
return;
}

if (!process.env.GOOGLE_API_KEY) {
console.error('❌ GOOGLE_API_KEY is not set in environment variables');
console.log('Please add your Google API key to the .env file');
return;
}

const langbase = new Langbase({
apiKey: process.env.LANGBASE_API_KEY!
});

try {
const result = await langbase.images.generate({
prompt: "A serene mountain landscape at sunset with a crystal clear lake reflecting the sky",
model: "together:black-forest-labs/FLUX.1-schnell-Free",
width: 1024,
height: 1024,
n: 1,
apiKey: process.env.TOGETHER_API_KEY!,
});

if (!result?.choices?.[0]?.message?.images?.[0]?.image_url?.url) {
console.error('❌ Image generation did not return an image. Full response:', result);
return;
}

console.log(result);
} catch (error) {
console.error('❌ Error generating image:', error);
}
}

main();
12 changes: 10 additions & 2 deletions examples/nodejs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,25 @@
"threads.messages.list": "npx tsx ./threads/threads.messages.list.ts",
"threads.get": "npx tsx ./threads/threads.get.ts",
"workflow": "npx tsx ./workflows/workflows.ts",
"agent.run.mcp": "npx tsx ./agent/agent.run.mcp.ts"
"agent.run.mcp": "npx tsx ./agent/agent.run.mcp.ts",
"images.openai": "npx tsx ./images/openai.ts",
"images.google": "npx tsx ./images/google.ts",
"images.together": "npx tsx ./images/together.ts",
"images.openrouter": "npx tsx ./images/openrouter.ts"

},
"keywords": [],
"author": "Ahmad Awais <me@AhmadAwais.com> (https://twitter.com/MrAhmadAwais)",
"license": "UNLICENSED",
"dependencies": {
"@langbase/cli": "^0.1.7",
"dotenv": "^16.4.5",
"langbase": "1.2.3",
"langbase": "workspace:*",
"uuid": "^11.1.0",
"zod": "^3.21.4",
"zod-to-json-schema": "^3.24.5"
},
"devDependencies": {
"tsx": "^4.19.1"
}
}
6 changes: 6 additions & 0 deletions examples/nodejs/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,10 @@ npm run thread.delete

# agent
npm run agent.run.mcp

# images
npm run images.openai
npm run images.google
npm run images.together
npm run images.openrouter
```
1 change: 1 addition & 0 deletions packages/langbase/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './langbase/langbase';
export * from './pipes/pipes';
export * from './lib/helpers';
export * from './langbase/workflows';
export * from './langbase/images';
90 changes: 90 additions & 0 deletions packages/langbase/src/langbase/images.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import {Request} from '../common/request';

export interface ImageGenerationOptions {
prompt: string;
model: string;
width?: number;
height?: number;
image_url?: string;
steps?: number;
n?: number;
negative_prompt?: string;
apiKey: string;
[key: string]: any;
}

export interface ImageGenerationResponse {
id: string;
provider: string;
model: string;
object: string;
created: number;
choices: Array<{
logprobs: null;
finish_reason: string;
native_finish_reason: string;
index: number;
message: {
role: string;
content: string | null;
images: Array<{
type: string;
image_url: {
url: string;
};
index: number;
}>;
};
}>;
usage: {
prompt_tokens: number;
completion_tokens: number;
total_tokens: number;
prompt_tokens_details: {
cached_tokens: number;
};
completion_tokens_details: {
reasoning_tokens: number;
image_tokens: number;
};
};
}

export class Images {
private request: Request;

constructor(request: Request) {
this.request = request;
}

/**
* Generate images using various AI providers
*
* @param options - Image generation options
* @returns Promise that resolves to the image generation response
*/
async generate(
options: ImageGenerationOptions,
): Promise<ImageGenerationResponse> {
// Comprehensive input validation
if (!options) {
throw new Error('Image generation options are required.');
}

// Extract apiKey from options for headers, remove from body
const {apiKey, ...imageParams} = options;

try {
return await this.request.post<ImageGenerationResponse>({
endpoint: '/v1/images',
body: imageParams,
headers: {
'LB-LLM-Key': apiKey,
},
});
} catch (error: any) {
console.error(error);
throw new Error(error.message);
}
}
}
19 changes: 18 additions & 1 deletion packages/langbase/src/langbase/langbase.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import {convertDocToFormData} from '@/lib/utils/doc-to-formdata';
import {Request} from '../common/request';
import {Workflow} from './workflows';
import {
Images,
ImageGenerationOptions,
ImageGenerationResponse,
} from './images';

export type Role = 'user' | 'assistant' | 'system' | 'tool';

Expand Down Expand Up @@ -646,6 +651,12 @@ export class Langbase {
create: (trace: any) => Promise<any>;
};

public images: {
generate: (
options: ImageGenerationOptions,
) => Promise<ImageGenerationResponse>;
};

constructor(options?: LangbaseOptions) {
this.baseUrl = options?.baseUrl ?? 'https://api.langbase.com';
this.apiKey = options?.apiKey ?? '';
Expand Down Expand Up @@ -737,6 +748,12 @@ export class Langbase {
this.traces = {
create: this.createTrace.bind(this),
};

// Initialize images primitive
const imagesInstance = new Images(this.request);
this.images = {
generate: imagesInstance.generate.bind(imagesInstance),
};
}

private async runPipe(
Expand Down Expand Up @@ -942,7 +959,7 @@ export class Langbase {
Authorization: `Bearer ${this.apiKey}`,
'Content-Type': options.contentType,
},
body: options.document,
body: options.document as any,
});
} catch (error) {
throw error;
Expand Down
Loading