From 716adb265fdd61aa2a9b1b93a333cf2fef83947c Mon Sep 17 00:00:00 2001 From: Ankit Kumar Work Date: Fri, 3 Oct 2025 21:10:41 +0530 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=93=A6=20NEW:=20Images=20Primitive?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/nodejs/.env.example | 10 +++ examples/nodejs/images/google.ts | 36 +++++++++ examples/nodejs/images/openai.ts | 36 +++++++++ examples/nodejs/images/openrouter.ts | 37 +++++++++ examples/nodejs/images/together.ts | 42 ++++++++++ examples/nodejs/package.json | 12 ++- examples/nodejs/readme.md | 7 +- packages/langbase/src/index.ts | 1 + packages/langbase/src/langbase/images.ts | 91 ++++++++++++++++++++++ packages/langbase/src/langbase/langbase.ts | 13 +++- 10 files changed, 281 insertions(+), 4 deletions(-) create mode 100644 examples/nodejs/images/google.ts create mode 100644 examples/nodejs/images/openai.ts create mode 100644 examples/nodejs/images/openrouter.ts create mode 100644 examples/nodejs/images/together.ts create mode 100644 packages/langbase/src/langbase/images.ts diff --git a/examples/nodejs/.env.example b/examples/nodejs/.env.example index 45e27cf..15716e3 100644 --- a/examples/nodejs/.env.example +++ b/examples/nodejs/.env.example @@ -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="" diff --git a/examples/nodejs/images/google.ts b/examples/nodejs/images/google.ts new file mode 100644 index 0000000..b5dff1f --- /dev/null +++ b/examples/nodejs/images/google.ts @@ -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(); \ No newline at end of file diff --git a/examples/nodejs/images/openai.ts b/examples/nodejs/images/openai.ts new file mode 100644 index 0000000..0dd17dc --- /dev/null +++ b/examples/nodejs/images/openai.ts @@ -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(); \ No newline at end of file diff --git a/examples/nodejs/images/openrouter.ts b/examples/nodejs/images/openrouter.ts new file mode 100644 index 0000000..bd7b21f --- /dev/null +++ b/examples/nodejs/images/openrouter.ts @@ -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(); \ No newline at end of file diff --git a/examples/nodejs/images/together.ts b/examples/nodejs/images/together.ts new file mode 100644 index 0000000..a31e0ec --- /dev/null +++ b/examples/nodejs/images/together.ts @@ -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(); \ No newline at end of file diff --git a/examples/nodejs/package.json b/examples/nodejs/package.json index 95e7372..5bf1187 100644 --- a/examples/nodejs/package.json +++ b/examples/nodejs/package.json @@ -44,7 +44,12 @@ "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 (https://twitter.com/MrAhmadAwais)", @@ -52,9 +57,12 @@ "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" } } diff --git a/examples/nodejs/readme.md b/examples/nodejs/readme.md index 7cc72f0..edcc943 100644 --- a/examples/nodejs/readme.md +++ b/examples/nodejs/readme.md @@ -53,4 +53,9 @@ 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 diff --git a/packages/langbase/src/index.ts b/packages/langbase/src/index.ts index d583556..be6e340 100644 --- a/packages/langbase/src/index.ts +++ b/packages/langbase/src/index.ts @@ -2,3 +2,4 @@ export * from './langbase/langbase'; export * from './pipes/pipes'; export * from './lib/helpers'; export * from './langbase/workflows'; +export * from './langbase/images'; diff --git a/packages/langbase/src/langbase/images.ts b/packages/langbase/src/langbase/images.ts new file mode 100644 index 0000000..abb0a74 --- /dev/null +++ b/packages/langbase/src/langbase/images.ts @@ -0,0 +1,91 @@ +import {Request} from '../common/request'; + +export interface ImageGenerationOptions { + prompt: string; + model: string; + width?: number; + height?: number; + image_url?: string; + steps?: number; + n?: number; + 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 { + // 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({ + endpoint: '/v1/images', + body: imageParams, + headers: { + 'LB-LLM-Key': apiKey, + }, + }); + } catch (error: any) { + console.error(error); + throw new Error( + error.message, + ); + } + } +} \ No newline at end of file diff --git a/packages/langbase/src/langbase/langbase.ts b/packages/langbase/src/langbase/langbase.ts index b6e886f..572ea2e 100644 --- a/packages/langbase/src/langbase/langbase.ts +++ b/packages/langbase/src/langbase/langbase.ts @@ -1,6 +1,7 @@ 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'; @@ -646,6 +647,10 @@ export class Langbase { create: (trace: any) => Promise; }; + public images: { + generate: (options: ImageGenerationOptions) => Promise; + }; + constructor(options?: LangbaseOptions) { this.baseUrl = options?.baseUrl ?? 'https://api.langbase.com'; this.apiKey = options?.apiKey ?? ''; @@ -737,6 +742,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( @@ -942,7 +953,7 @@ export class Langbase { Authorization: `Bearer ${this.apiKey}`, 'Content-Type': options.contentType, }, - body: options.document, + body: options.document as any, }); } catch (error) { throw error; From 895bc4d2d1c9dc82feb73cdd9cae1a3acbd50b56 Mon Sep 17 00:00:00 2001 From: Ankit Kumar Work Date: Wed, 8 Oct 2025 01:05:23 +0530 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=91=8C=20IMPROVE:=20Image=20Input?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/nodejs/readme.md | 1 + packages/langbase/src/langbase/images.ts | 17 ++++++++--------- packages/langbase/src/langbase/langbase.ts | 10 ++++++++-- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/examples/nodejs/readme.md b/examples/nodejs/readme.md index edcc943..c2b019f 100644 --- a/examples/nodejs/readme.md +++ b/examples/nodejs/readme.md @@ -59,3 +59,4 @@ npm run images.openai npm run images.google npm run images.together npm run images.openrouter +``` diff --git a/packages/langbase/src/langbase/images.ts b/packages/langbase/src/langbase/images.ts index abb0a74..cd510a3 100644 --- a/packages/langbase/src/langbase/images.ts +++ b/packages/langbase/src/langbase/images.ts @@ -8,6 +8,7 @@ export interface ImageGenerationOptions { image_url?: string; steps?: number; n?: number; + negative_prompt?: string; apiKey: string; [key: string]: any; } @@ -58,16 +59,16 @@ export class Images { /** * 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 { + async generate( + options: ImageGenerationOptions, + ): Promise { // Comprehensive input validation if (!options) { - throw new Error( - 'Image generation options are required.', - ); + throw new Error('Image generation options are required.'); } // Extract apiKey from options for headers, remove from body @@ -83,9 +84,7 @@ export class Images { }); } catch (error: any) { console.error(error); - throw new Error( - error.message, - ); + throw new Error(error.message); } } -} \ No newline at end of file +} diff --git a/packages/langbase/src/langbase/langbase.ts b/packages/langbase/src/langbase/langbase.ts index 572ea2e..5124578 100644 --- a/packages/langbase/src/langbase/langbase.ts +++ b/packages/langbase/src/langbase/langbase.ts @@ -1,7 +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'; +import { + Images, + ImageGenerationOptions, + ImageGenerationResponse, +} from './images'; export type Role = 'user' | 'assistant' | 'system' | 'tool'; @@ -648,7 +652,9 @@ export class Langbase { }; public images: { - generate: (options: ImageGenerationOptions) => Promise; + generate: ( + options: ImageGenerationOptions, + ) => Promise; }; constructor(options?: LangbaseOptions) {