Initial commit

This commit is contained in:
Zhongwei Li
2025-11-30 08:25:12 +08:00
commit 7a35a34caa
30 changed files with 8396 additions and 0 deletions

View File

@@ -0,0 +1,12 @@
{
"name": "openai-api",
"description": "Build with OpenAIs stateless APIs - Chat Completions (GPT-5, GPT-4o), Embeddings, Images (DALL-E 3), Audio (Whisper + TTS), and Moderation. Includes Node.js SDK and fetch-based approaches for Cloudflare Workers. Use when: implementing chat completions with GPT-5/GPT-4o, streaming responses with SSE, using function calling/tools, creating structured outputs with JSON schemas, generating embeddings for RAG (text-embedding-3-small/large), generating images with DALL-E 3, editing images with GPT-Ima",
"version": "1.0.0",
"author": {
"name": "Jeremy Dawes",
"email": "jeremy@jezweb.net"
},
"skills": [
"./"
]
}

359
NEXT-SESSION.md Normal file
View File

@@ -0,0 +1,359 @@
# OpenAI API Skill - Phase 2 Session Plan
**Created**: 2025-10-25
**Status**: Phase 1 Complete ✅ - Ready for Phase 2
**Estimated Phase 2 Time**: 3-4 hours
---
## Phase 1 Completion Summary ✅
### What's Done
1. **SKILL.md** - Complete foundation (900+ lines)
- ✅ Full Chat Completions API documentation
- ✅ GPT-5 series coverage with unique parameters
- ✅ Streaming patterns (both SDK and fetch)
- ✅ Function calling complete guide
- ✅ Structured outputs examples
- ✅ Vision (GPT-4o) coverage
- ✅ Error handling section
- ✅ Rate limits section
- ✅ Production best practices
- ✅ Relationship to openai-responses
2. **README.md** - Complete with comprehensive keywords ✅
- All auto-trigger keywords
- When to use guide
- Quick examples
- Known issues table
- Token efficiency metrics
3. **Core Templates** (6 files) ✅
- chat-completion-basic.ts
- chat-completion-nodejs.ts
- streaming-chat.ts
- streaming-fetch.ts
- function-calling.ts
- cloudflare-worker.ts
- package.json
4. **Reference Docs** (1 file) ✅
- top-errors.md (10 common errors with solutions)
5. **Scripts** (1 file) ✅
- check-versions.sh
6. **Research**
- Complete research log: `/planning/research-logs/openai-api.md`
### Current Status
- **Usable NOW**: Chat Completions fully documented and working
- **Phase 1**: Production-ready for primary use case (Chat Completions)
- **Phase 2**: Remaining APIs to be completed
---
## Phase 2 Tasks
### 1. Complete SKILL.md Sections (2-3 hours)
#### Embeddings API Section
Location: `SKILL.md` line ~600 (marked as "Phase 2")
**Content to Add**:
- Models: text-embedding-3-small, text-embedding-3-large, text-embedding-ada-002
- Custom dimensions parameter
- Batch processing patterns
- Request/response examples
- RAG integration patterns
- Dimension reduction techniques
- Token limits (8192 per input, 300k summed)
**Source**: `/planning/research-logs/openai-api.md` Section 2
#### Images API Section
Location: `SKILL.md` line ~620 (marked as "Phase 2")
**Content to Add**:
- DALL-E 3 generation (/v1/images/generations)
- Image editing (/v1/images/edits)
- Parameters: size, quality, style, response_format
- Quality settings (standard vs HD)
- Style options (vivid vs natural)
- Transparent backgrounds
- Output compression
- Request/response examples
**Source**: `/planning/research-logs/openai-api.md` Section 3
#### Audio API Section
Location: `SKILL.md` line ~640 (marked as "Phase 2")
**Content to Add**:
- Whisper transcription (/v1/audio/transcriptions)
- Text-to-Speech (/v1/audio/speech)
- Models: whisper-1, tts-1, tts-1-hd, gpt-4o-mini-tts
- 11 voices (alloy, ash, ballad, coral, echo, fable, onyx, nova, sage, shimmer, verse)
- Audio formats: mp3, opus, aac, flac, wav, pcm
- Speed control (0.25 to 4.0)
- Voice instructions (gpt-4o-mini-tts only)
- Streaming audio (sse format)
- Request/response examples
**Source**: `/planning/research-logs/openai-api.md` Section 4
#### Moderation API Section
Location: `SKILL.md` line ~660 (marked as "Phase 2")
**Content to Add**:
- Moderation endpoint (/v1/moderations)
- Model: omni-moderation-latest
- Categories: sexual, hate, harassment, self-harm, violence, etc.
- Category scores (0-1 confidence)
- Multi-modal moderation (text + images)
- Batch moderation
- Request/response examples
- Threshold recommendations
**Source**: `/planning/research-logs/openai-api.md` Section 5
### 2. Create Remaining Templates (9 files, 1-2 hours)
#### Embeddings Templates
1. **embeddings.ts** - Basic embeddings generation
```typescript
// text-embedding-3-small and text-embedding-3-large examples
// Custom dimensions
// Batch processing
```
#### Images Templates
2. **image-generation.ts** - DALL-E 3 generation
```typescript
// Basic generation
// Quality and style options
// Transparent backgrounds
```
3. **image-editing.ts** - Image editing
```typescript
// Edit with mask
// Transparent backgrounds
// Compression options
```
#### Audio Templates
4. **audio-transcription.ts** - Whisper transcription
```typescript
// File transcription
// Supported formats
```
5. **text-to-speech.ts** - TTS generation
```typescript
// All 11 voices
// gpt-4o-mini-tts with instructions
// Speed control
// Format options
```
#### Moderation Templates
6. **moderation.ts** - Content moderation
```typescript
// Basic moderation
// Category filtering
// Batch moderation
```
#### Advanced Templates
7. **structured-output.ts** - JSON schema validation
```typescript
// Using response_format with JSON schema
// Strict mode
// Complex nested schemas
```
8. **vision-gpt4o.ts** - Vision examples
```typescript
// Image via URL
// Image via base64
// Multiple images
```
9. **rate-limit-handling.ts** - Production retry logic
```typescript
// Exponential backoff
// Rate limit header monitoring
// Queue implementation
```
### 3. Create Remaining Reference Docs (7 files, 1 hour)
1. **models-guide.md**
- GPT-5 vs GPT-4o vs GPT-4 Turbo comparison table
- When to use each model
- Cost comparison
- Capability matrix
2. **function-calling-patterns.md**
- Advanced tool patterns
- Parallel tool calls
- Dynamic tool generation
- Error handling in tools
3. **structured-output-guide.md**
- JSON schema best practices
- Complex nested schemas
- Validation strategies
- Error handling
4. **embeddings-guide.md**
- Model comparison (small vs large vs ada-002)
- Dimension selection
- RAG patterns
- Cosine similarity examples
- Batch processing strategies
5. **images-guide.md**
- DALL-E 3 prompting tips
- Quality vs cost trade-offs
- Style guide (vivid vs natural)
- Transparent backgrounds use cases
- Editing best practices
6. **audio-guide.md**
- Voice selection guide
- TTS vs real recordings
- Whisper accuracy tips
- Format selection
7. **cost-optimization.md**
- Model selection strategies
- Caching patterns
- Batch processing
- Token optimization
- Rate limit management
### 4. Testing & Validation (30 min)
- [ ] Install skill: `./scripts/install-skill.sh openai-api`
- [ ] Test auto-discovery with Claude Code
- [ ] Verify all templates compile (TypeScript check)
- [ ] Test at least 2-3 templates end-to-end with real API calls
- [ ] Check against ONE_PAGE_CHECKLIST.md
### 5. Final Documentation (30 min)
- [ ] Update roadmap: `/planning/skills-roadmap.md`
- Mark openai-api as complete
- Add completion metrics (token savings, errors prevented)
- Update status to Production Ready
- [ ] Update SKILL.md
- Remove all "Phase 2" markers
- Update status to "Production Ready ✅"
- Update Last Updated date
- [ ] Create final commit message
---
## Quick Start for Phase 2 Session
### Context to Load
1. Read this file (NEXT-SESSION.md)
2. Read `/planning/research-logs/openai-api.md` for all API details
3. Review current `SKILL.md` to see structure
### First Steps
```bash
# 1. Navigate to skill directory
cd /home/jez/Documents/claude-skills/skills/openai-api
# 2. Verify current state
ls -la templates/
ls -la references/
# 3. Start with Embeddings API section
# Edit SKILL.md around line 600
```
### Development Order
1. **Embeddings** (most requested after Chat Completions)
2. **Images** (DALL-E 3 popular)
3. **Audio** (Whisper + TTS)
4. **Moderation** (simple, quick)
5. **Templates** (parallel work)
6. **Reference docs** (parallel work)
7. **Testing**
8. **Commit**
---
## Reference Files
### Already Created
- `SKILL.md` - Foundation with Chat Completions complete
- `README.md` - Complete
- `templates/chat-completion-basic.ts` ✅
- `templates/chat-completion-nodejs.ts` ✅
- `templates/streaming-chat.ts` ✅
- `templates/streaming-fetch.ts` ✅
- `templates/function-calling.ts` ✅
- `templates/cloudflare-worker.ts` ✅
- `templates/package.json` ✅
- `references/top-errors.md` ✅
- `scripts/check-versions.sh` ✅
- `/planning/research-logs/openai-api.md` ✅
### To Be Created (Phase 2)
- **Templates** (9 files)
- **References** (7 files)
- **SKILL.md sections** (4 API sections)
---
## Success Criteria
### Phase 2 Complete When:
- [ ] All 4 API sections in SKILL.md complete (Embeddings, Images, Audio, Moderation)
- [ ] All 14 templates created (6 done + 9 new = 15 total)
- [ ] All 10 reference docs created (1 done + 7 new = 8 total minimum)
- [ ] Auto-discovery working
- [ ] All templates tested
- [ ] Token savings >= 60% (measured)
- [ ] Errors prevented: 10+ (documented)
- [ ] Roadmap updated
- [ ] Committed to git
- [ ] Status: Production Ready ✅
---
## Token Efficiency Target
**Phase 1 Baseline**:
- Manual Chat Completions setup: ~10,000 tokens
- With Phase 1 skill: ~4,000 tokens
- **Savings: ~60%**
**Phase 2 Target** (full skill):
- Manual full API setup: ~21,000 tokens
- With complete skill: ~8,500 tokens
- **Target savings: ~60%**
---
## Notes
- All research is complete and documented
- Templates follow consistent patterns
- Both SDK and fetch approaches where applicable
- Focus on copy-paste ready code
- Production patterns emphasized
- Clear relationship to openai-responses skill
---
**Ready to Execute Phase 2!** 🚀
When starting next session, simply read this file and continue from Phase 2 Tasks.

3
README.md Normal file
View File

@@ -0,0 +1,3 @@
# openai-api
Build with OpenAIs stateless APIs - Chat Completions (GPT-5, GPT-4o), Embeddings, Images (DALL-E 3), Audio (Whisper + TTS), and Moderation. Includes Node.js SDK and fetch-based approaches for Cloudflare Workers. Use when: implementing chat completions with GPT-5/GPT-4o, streaming responses with SSE, using function calling/tools, creating structured outputs with JSON schemas, generating embeddings for RAG (text-embedding-3-small/large), generating images with DALL-E 3, editing images with GPT-Ima

2099
SKILL.md Normal file

File diff suppressed because it is too large Load Diff

149
plugin.lock.json Normal file
View File

@@ -0,0 +1,149 @@
{
"$schema": "internal://schemas/plugin.lock.v1.json",
"pluginId": "gh:jezweb/claude-skills:skills/openai-api",
"normalized": {
"repo": null,
"ref": "refs/tags/v20251128.0",
"commit": "640e809b4c50f227f1c985466847b4197a913fa3",
"treeHash": "c167b926ac69a55fb556877117e730da715805681a6285504843e57f20cfd21a",
"generatedAt": "2025-11-28T10:19:00.716947Z",
"toolVersion": "publish_plugins.py@0.2.0"
},
"origin": {
"remote": "git@github.com:zhongweili/42plugin-data.git",
"branch": "master",
"commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390",
"repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data"
},
"manifest": {
"name": "openai-api",
"description": "Build with OpenAIs stateless APIs - Chat Completions (GPT-5, GPT-4o), Embeddings, Images (DALL-E 3), Audio (Whisper + TTS), and Moderation. Includes Node.js SDK and fetch-based approaches for Cloudflare Workers. Use when: implementing chat completions with GPT-5/GPT-4o, streaming responses with SSE, using function calling/tools, creating structured outputs with JSON schemas, generating embeddings for RAG (text-embedding-3-small/large), generating images with DALL-E 3, editing images with GPT-Ima",
"version": "1.0.0"
},
"content": {
"files": [
{
"path": "README.md",
"sha256": "c2126d7a1ccbb83655c1cf0143c48db8023a9c552d401fa1d76e33c83132553a"
},
{
"path": "SKILL.md",
"sha256": "34238fe28c0f94267ac1b6307250aaffa0a6f67ea94c5e59f8cf254924f97ddf"
},
{
"path": "NEXT-SESSION.md",
"sha256": "04e6cc8e23dcf03a467a62130e403941009a00eb036e2669426249ee8f4c8d32"
},
{
"path": "references/cost-optimization.md",
"sha256": "9acec1bc7d1a1d176efa33ed7910548484b74c7288564ee5e57663fbe92e69c7"
},
{
"path": "references/embeddings-guide.md",
"sha256": "fd58048de0d8e4d2116c88726ac52b3c36e61d7aafaa94414de624e1579f5730"
},
{
"path": "references/audio-guide.md",
"sha256": "08bd89b24c521130f26723416f8f751f7a330b60ad8ca77afe80427b205b0554"
},
{
"path": "references/top-errors.md",
"sha256": "71dcdec275b4a1b007b09a16eec4dcfa0a177f226dde9b96f071a19ace04e910"
},
{
"path": "references/images-guide.md",
"sha256": "d6c0c1bee83ac9be0ade94f97d8cd4a0a6c06f60064c8d849eabd3b803e15ed6"
},
{
"path": "references/models-guide.md",
"sha256": "0f408d4983895d58afce35abcdb9382d25301edb7229743a927f59097fe33484"
},
{
"path": "references/function-calling-patterns.md",
"sha256": "9959c4124ef3c9883c106e8927a7fde7c0d1550d83336cb7299b6963644f2515"
},
{
"path": "references/structured-output-guide.md",
"sha256": "bbd12b10cd19bcef4341913653bbe3a98c71c708e04b3f01fd898d31e3888c91"
},
{
"path": "scripts/check-versions.sh",
"sha256": "b2877a9de67c5da5309e4a919c1474a0ceb7cc9874aa5f4781cbe1a7206ed4d2"
},
{
"path": ".claude-plugin/plugin.json",
"sha256": "5a6ffab924feea89312898424302a28734d39d97255bdce60dfbf2e872512b21"
},
{
"path": "templates/chat-completion-nodejs.ts",
"sha256": "af58be6f26a14d4bdbc87d42fe5305c25c5cb2139170edb6ecee5363cb0cba43"
},
{
"path": "templates/chat-completion-basic.ts",
"sha256": "0f5d26a3ddfb54e3c7c94139e7596c514b56e68545d131f9e12d08d598442144"
},
{
"path": "templates/audio-transcription.ts",
"sha256": "09b14269eaad9ae51878f0164904cc6524d18260fc14075f7cca82cc59c4e1d4"
},
{
"path": "templates/image-editing.ts",
"sha256": "8cc85ee5c578ed7f0c40794a25d8a4212fac90ef822a9f84a5c15cfe99107a80"
},
{
"path": "templates/embeddings.ts",
"sha256": "b0c83139d1834922d7bcbac7257dc19f58c40cdf23069ae2051b536f6d0683c9"
},
{
"path": "templates/function-calling.ts",
"sha256": "42e646d01b2832583b2d7e85601796091f2cb9cffbe3b24c9ec5f76abe080e4b"
},
{
"path": "templates/streaming-chat.ts",
"sha256": "6a54bd2562441ce8f7da3f1e78cd1df2d371f243d1163ce29a972c14eaa49b87"
},
{
"path": "templates/package.json",
"sha256": "52dec3d81f19598e3ea8021e0732369750543093044539ab893de598a6f1ac80"
},
{
"path": "templates/text-to-speech.ts",
"sha256": "8243d6f3bd8762485e3b575fb8086b5a3767539520f6a21ca33af0f6a33ccf54"
},
{
"path": "templates/cloudflare-worker.ts",
"sha256": "968ad9bec422273f1ac40633465f9783416b40557049925dfba96f37abcb2ce6"
},
{
"path": "templates/moderation.ts",
"sha256": "21e01a70175dc6d0b44dab42c896c17a84f7e929d45448c62a2e902d7d8aff0c"
},
{
"path": "templates/vision-gpt4o.ts",
"sha256": "ab53775fbe5039db8d8eccc98853ad25cdd02cc3200cecd04d73296b68d39b26"
},
{
"path": "templates/streaming-fetch.ts",
"sha256": "119a744c67c5fffa98711027a06f2e768bdcd5924ebfe14d5fbd9af175d974bf"
},
{
"path": "templates/image-generation.ts",
"sha256": "d47bae2fda13d85147793a14f13a2c898765eb1ebb2768ece4961fd3d4563fee"
},
{
"path": "templates/rate-limit-handling.ts",
"sha256": "7b0be745af3ba75432b2956ffd1f4eb818d814ce175b7a390937f66590a7e961"
},
{
"path": "templates/structured-output.ts",
"sha256": "5588451c403df2aef10d95805cd14053ef51ed102994f26bf4d4ff5bc11bee99"
}
],
"dirSha256": "c167b926ac69a55fb556877117e730da715805681a6285504843e57f20cfd21a"
},
"security": {
"scannedAt": null,
"scannerVersion": null,
"flags": []
}
}

205
references/audio-guide.md Normal file
View File

@@ -0,0 +1,205 @@
# Audio Guide (Whisper & TTS)
**Last Updated**: 2025-10-25
Complete guide to OpenAI's Audio API for transcription and text-to-speech.
---
## Whisper Transcription
### Supported Formats
- mp3, mp4, mpeg, mpga, m4a, wav, webm
### Best Practices
**Audio Quality**:
- Use clear audio with minimal background noise
- 16 kHz or higher sample rate recommended
- Mono or stereo both supported
**File Size**:
- Max file size: 25 MB
- For larger files: split into chunks or compress
**Languages**:
- Whisper automatically detects language
- Supports 50+ languages
- Best results with English, Spanish, French, German, Chinese
**Limitations**:
- May struggle with heavy accents
- Background noise reduces accuracy
- Very quiet audio may fail
---
## Text-to-Speech (TTS)
### Model Selection
| Model | Quality | Latency | Features | Best For |
|-------|---------|---------|----------|----------|
| tts-1 | Standard | Lowest | Basic TTS | Real-time streaming |
| tts-1-hd | High | Medium | Better fidelity | Offline audio, podcasts |
| gpt-4o-mini-tts | Best | Medium | Voice instructions, streaming | Maximum control |
### Voice Selection Guide
| Voice | Character | Best For |
|-------|-----------|----------|
| alloy | Neutral, balanced | General use, professional |
| ash | Clear, professional | Business, presentations |
| ballad | Warm, storytelling | Narration, audiobooks |
| coral | Soft, friendly | Customer service, greetings |
| echo | Calm, measured | Meditation, calm content |
| fable | Expressive, narrative | Stories, entertainment |
| onyx | Deep, authoritative | News, serious content |
| nova | Bright, energetic | Marketing, enthusiastic content |
| sage | Wise, thoughtful | Educational, informative |
| shimmer | Gentle, soothing | Relaxation, sleep content |
| verse | Poetic, rhythmic | Poetry, artistic content |
### Voice Instructions (gpt-4o-mini-tts only)
```typescript
// Professional tone
{
model: 'gpt-4o-mini-tts',
voice: 'ash',
input: 'Welcome to our service',
instructions: 'Speak in a calm, professional, and friendly tone suitable for customer service.',
}
// Energetic marketing
{
model: 'gpt-4o-mini-tts',
voice: 'nova',
input: 'Don\'t miss this sale!',
instructions: 'Use an enthusiastic, energetic tone perfect for marketing and advertisements.',
}
// Meditation guidance
{
model: 'gpt-4o-mini-tts',
voice: 'shimmer',
input: 'Take a deep breath',
instructions: 'Adopt a calm, soothing voice suitable for meditation and relaxation guidance.',
}
```
### Speed Control
```typescript
// Slow (0.5x)
{ speed: 0.5 } // Good for: Learning, accessibility
// Normal (1.0x)
{ speed: 1.0 } // Default
// Fast (1.5x)
{ speed: 1.5 } // Good for: Previews, time-saving
// Very fast (2.0x)
{ speed: 2.0 } // Good for: Quick previews only
```
Range: 0.25 to 4.0
### Audio Format Selection
| Format | Compression | Quality | Best For |
|--------|-------------|---------|----------|
| mp3 | Lossy | Good | Maximum compatibility |
| opus | Lossy | Excellent | Web streaming, low bandwidth |
| aac | Lossy | Good | iOS, Apple devices |
| flac | Lossless | Best | Archiving, editing |
| wav | Uncompressed | Best | Editing, processing |
| pcm | Raw | Best | Low-level processing |
---
## Common Patterns
### 1. Transcribe Interview
```typescript
const transcription = await openai.audio.transcriptions.create({
file: fs.createReadStream('./interview.mp3'),
model: 'whisper-1',
});
// Save transcript
fs.writeFileSync('./interview.txt', transcription.text);
```
### 2. Generate Podcast Narration
```typescript
const script = "Welcome to today's podcast...";
const audio = await openai.audio.speech.create({
model: 'tts-1-hd',
voice: 'fable',
input: script,
response_format: 'mp3',
});
const buffer = Buffer.from(await audio.arrayBuffer());
fs.writeFileSync('./podcast.mp3', buffer);
```
### 3. Multi-Voice Conversation
```typescript
// Speaker 1
const speaker1 = await openai.audio.speech.create({
model: 'tts-1',
voice: 'onyx',
input: 'Hello, how are you?',
});
// Speaker 2
const speaker2 = await openai.audio.speech.create({
model: 'tts-1',
voice: 'nova',
input: 'I\'m doing great, thanks!',
});
// Combine audio files (requires audio processing library)
```
---
## Cost Optimization
1. **Use tts-1 for real-time** (cheaper, faster)
2. **Use tts-1-hd for final production** (better quality)
3. **Cache generated audio** (deterministic for same input)
4. **Choose appropriate format** (opus for web, mp3 for compatibility)
5. **Batch transcriptions** with delays to avoid rate limits
---
## Common Issues
### Transcription Accuracy
- Improve audio quality
- Reduce background noise
- Ensure adequate volume levels
- Use supported audio formats
### TTS Naturalness
- Test different voices
- Use voice instructions (gpt-4o-mini-tts)
- Adjust speed for better pacing
- Add punctuation for natural pauses
### File Size
- Compress audio before transcribing
- Choose lossy formats (mp3, opus) for TTS
- Use appropriate bitrates
---
**See Also**: Official Audio Guide (https://platform.openai.com/docs/guides/speech-to-text)

View File

@@ -0,0 +1,278 @@
# Cost Optimization Guide
**Last Updated**: 2025-10-25
Strategies to minimize OpenAI API costs while maintaining quality.
---
## Model Selection Strategies
### 1. Model Cascading
Start with cheaper models, escalate only when needed:
```typescript
async function smartCompletion(prompt: string) {
// Try gpt-5-nano first
const nanoResult = await openai.chat.completions.create({
model: 'gpt-5-nano',
messages: [{ role: 'user', content: prompt }],
});
// Validate quality
if (isGoodEnough(nanoResult)) {
return nanoResult;
}
// Escalate to gpt-5-mini
const miniResult = await openai.chat.completions.create({
model: 'gpt-5-mini',
messages: [{ role: 'user', content: prompt }],
});
if (isGoodEnough(miniResult)) {
return miniResult;
}
// Final escalation to gpt-5
return await openai.chat.completions.create({
model: 'gpt-5',
messages: [{ role: 'user', content: prompt }],
});
}
```
### 2. Task-Based Model Selection
| Task | Model | Why |
|------|-------|-----|
| Simple chat | gpt-5-nano | Fast, cheap, sufficient |
| Summarization | gpt-5-mini | Good quality, cost-effective |
| Code generation | gpt-5 | Best reasoning, worth the cost |
| Data extraction | gpt-4o + structured output | Reliable, accurate |
| Vision tasks | gpt-4o | Only model with vision |
---
## Token Optimization
### 1. Limit max_tokens
```typescript
// ❌ No limit: May generate unnecessarily long responses
{
model: 'gpt-5',
messages,
}
// ✅ Set reasonable limit
{
model: 'gpt-5',
messages,
max_tokens: 500, // Prevent runaway generation
}
```
### 2. Trim Conversation History
```typescript
function trimHistory(messages: Message[], maxTokens: number = 4000) {
// Keep system message and recent messages
const system = messages.find(m => m.role === 'system');
const recent = messages.slice(-10); // Last 10 messages
return [system, ...recent].filter(Boolean);
}
```
### 3. Use Shorter Prompts
```typescript
// ❌ Verbose
"Please analyze the following text and provide a detailed summary of the main points, including any key takeaways and important details..."
// ✅ Concise
"Summarize key points:"
```
---
## Caching Strategies
### 1. Cache Embeddings
```typescript
const embeddingCache = new Map<string, number[]>();
async function getCachedEmbedding(text: string) {
if (embeddingCache.has(text)) {
return embeddingCache.get(text)!;
}
const response = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: text,
});
const embedding = response.data[0].embedding;
embeddingCache.set(text, embedding);
return embedding;
}
```
### 2. Cache Common Completions
```typescript
const completionCache = new Map<string, string>();
async function getCachedCompletion(prompt: string) {
const cacheKey = `${model}:${prompt}`;
if (completionCache.has(cacheKey)) {
return completionCache.get(cacheKey)!;
}
const result = await openai.chat.completions.create({
model: 'gpt-5-mini',
messages: [{ role: 'user', content: prompt }],
});
const content = result.choices[0].message.content;
completionCache.set(cacheKey, content!);
return content;
}
```
---
## Batch Processing
### 1. Use Embeddings Batch API
```typescript
// ❌ Individual requests (expensive)
for (const doc of documents) {
await openai.embeddings.create({
model: 'text-embedding-3-small',
input: doc,
});
}
// ✅ Batch request (cheaper)
const response = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: documents, // Array of up to 2048 documents
});
```
### 2. Group Similar Requests
```typescript
// Process non-urgent requests in batches during off-peak hours
const batchQueue: string[] = [];
function queueForBatch(prompt: string) {
batchQueue.push(prompt);
if (batchQueue.length >= 10) {
processBatch();
}
}
async function processBatch() {
// Process all at once
const results = await Promise.all(
batchQueue.map(prompt =>
openai.chat.completions.create({
model: 'gpt-5-nano',
messages: [{ role: 'user', content: prompt }],
})
)
);
batchQueue.length = 0;
return results;
}
```
---
## Feature-Specific Optimization
### Embeddings
1. **Use custom dimensions**: 256 instead of 1536 = 6x storage reduction
2. **Use text-embedding-3-small**: Cheaper than large, good for most use cases
3. **Batch requests**: Up to 2048 documents per request
### Images
1. **Use standard quality**: Unless HD is critical
2. **Use smaller sizes**: Generate 1024x1024 instead of 1792x1024 when possible
3. **Use natural style**: Cheaper than vivid
### Audio
1. **Use tts-1 for real-time**: Cheaper than tts-1-hd
2. **Use opus format**: Smaller files, good quality
3. **Cache generated audio**: Deterministic for same input
---
## Monitoring and Alerts
```typescript
interface CostTracker {
totalTokens: number;
totalCost: number;
requestCount: number;
}
const tracker: CostTracker = {
totalTokens: 0,
totalCost: 0,
requestCount: 0,
};
async function trackCosts(fn: () => Promise<any>) {
const result = await fn();
if (result.usage) {
tracker.totalTokens += result.usage.total_tokens;
tracker.requestCount++;
// Estimate cost (adjust rates based on actual pricing)
const cost = estimateCost(result.model, result.usage.total_tokens);
tracker.totalCost += cost;
// Alert if threshold exceeded
if (tracker.totalCost > 100) {
console.warn('Cost threshold exceeded!', tracker);
}
}
return result;
}
```
---
## Cost Reduction Checklist
- [ ] Use cheapest model that meets requirements
- [ ] Set max_tokens limits
- [ ] Trim conversation history
- [ ] Cache embeddings and common queries
- [ ] Batch requests when possible
- [ ] Use custom embedding dimensions (256-512)
- [ ] Monitor token usage
- [ ] Implement rate limiting
- [ ] Use structured outputs to avoid retries
- [ ] Compress prompts (remove unnecessary words)
---
**Estimated Savings**: Following these practices can reduce costs by 40-70% while maintaining quality.

View File

@@ -0,0 +1,187 @@
# Embeddings Guide
**Last Updated**: 2025-10-25
Complete guide to OpenAI's Embeddings API for semantic search, RAG, and clustering.
---
## Model Comparison
| Model | Default Dimensions | Custom Dimensions | Best For |
|-------|-------------------|-------------------|----------|
| text-embedding-3-large | 3072 | 256-3072 | Highest quality semantic search |
| text-embedding-3-small | 1536 | 256-1536 | Most applications, cost-effective |
| text-embedding-ada-002 | 1536 | Fixed | Legacy (use v3 models) |
---
## Dimension Selection
### Full Dimensions
- **text-embedding-3-small**: 1536 (default)
- **text-embedding-3-large**: 3072 (default)
- Use for maximum accuracy
### Reduced Dimensions
- **256 dims**: 4-12x storage reduction, minimal quality loss
- **512 dims**: 2-6x storage reduction, good quality
- Use for cost/storage optimization
```typescript
// Full dimensions (1536)
const full = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: 'Sample text',
});
// Reduced dimensions (256)
const reduced = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: 'Sample text',
dimensions: 256,
});
```
---
## RAG (Retrieval-Augmented Generation) Pattern
### 1. Build Knowledge Base
```typescript
const documents = [
'TypeScript is a superset of JavaScript',
'Python is a high-level programming language',
'React is a JavaScript library for UIs',
];
const embeddings = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: documents,
});
const knowledgeBase = documents.map((text, i) => ({
text,
embedding: embeddings.data[i].embedding,
}));
```
### 2. Query with Similarity Search
```typescript
// Embed user query
const queryEmbedding = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: 'What is TypeScript?',
});
// Find similar documents
const similarities = knowledgeBase.map(doc => ({
text: doc.text,
similarity: cosineSimilarity(queryEmbedding.data[0].embedding, doc.embedding),
}));
similarities.sort((a, b) => b.similarity - a.similarity);
const topResults = similarities.slice(0, 3);
```
### 3. Generate Answer with Context
```typescript
const context = topResults.map(r => r.text).join('\n\n');
const completion = await openai.chat.completions.create({
model: 'gpt-5',
messages: [
{ role: 'system', content: `Answer using this context:\n\n${context}` },
{ role: 'user', content: 'What is TypeScript?' },
],
});
```
---
## Similarity Metrics
### Cosine Similarity (Recommended)
```typescript
function cosineSimilarity(a: number[], b: number[]): number {
const dotProduct = a.reduce((sum, val, i) => sum + val * b[i], 0);
const magnitudeA = Math.sqrt(a.reduce((sum, val) => sum + val * val, 0));
const magnitudeB = Math.sqrt(b.reduce((sum, val) => sum + val * val, 0));
return dotProduct / (magnitudeA * magnitudeB);
}
```
### Euclidean Distance
```typescript
function euclideanDistance(a: number[], b: number[]): number {
return Math.sqrt(
a.reduce((sum, val, i) => sum + Math.pow(val - b[i], 2), 0)
);
}
```
---
## Batch Processing
```typescript
// Process up to 2048 documents
const embeddings = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: documents, // Array of strings
});
embeddings.data.forEach((item, index) => {
console.log(`Doc ${index}: ${item.embedding.length} dimensions`);
});
```
**Limits**:
- Max tokens per input: 8192
- Max summed tokens across all inputs: 300,000
- Array dimension max: 2048
---
## Best Practices
**Pre-processing**:
- Normalize text (lowercase, remove special chars)
- Be consistent across queries and documents
- Chunk long documents (max 8192 tokens)
**Storage**:
- Use custom dimensions (256-512) for storage optimization
- Store embeddings in vector databases (Pinecone, Weaviate, Qdrant)
- Cache embeddings (deterministic for same input)
**Search**:
- Use cosine similarity for comparison
- Normalize embeddings before storing (L2 normalization)
- Pre-filter with metadata before similarity search
**Don't**:
- Mix models (incompatible dimensions)
- Exceed token limits (8192 per input)
- Skip normalization
- Use raw embeddings without similarity metric
---
## Use Cases
1. **Semantic Search**: Find similar documents
2. **RAG**: Retrieve context for generation
3. **Clustering**: Group similar content
4. **Recommendations**: Content-based recommendations
5. **Anomaly Detection**: Detect outliers
6. **Duplicate Detection**: Find similar/duplicate content
---
**See Also**: Official Embeddings Guide (https://platform.openai.com/docs/guides/embeddings)

View File

@@ -0,0 +1,189 @@
# Function Calling Patterns
**Last Updated**: 2025-10-25
Advanced patterns for implementing function calling (tool calling) with OpenAI's Chat Completions API.
---
## Basic Pattern
```typescript
const tools = [
{
type: 'function',
function: {
name: 'get_weather',
description: 'Get current weather for a location',
parameters: {
type: 'object',
properties: {
location: { type: 'string', description: 'City name' },
unit: { type: 'string', enum: ['celsius', 'fahrenheit'] },
},
required: ['location'],
},
},
},
];
```
---
## Advanced Patterns
### 1. Parallel Tool Calls
The model can call multiple tools simultaneously:
```typescript
const completion = await openai.chat.completions.create({
model: 'gpt-5',
messages: [
{ role: 'user', content: 'What is the weather in SF and NYC?' }
],
tools: tools,
});
// Model may return multiple tool_calls
const toolCalls = completion.choices[0].message.tool_calls;
// Execute all in parallel
const results = await Promise.all(
toolCalls.map(call => executeFunction(call.function.name, call.function.arguments))
);
```
### 2. Dynamic Tool Generation
Generate tools based on runtime context:
```typescript
function generateTools(database: Database) {
const tables = database.getTables();
return tables.map(table => ({
type: 'function',
function: {
name: `query_${table.name}`,
description: `Query the ${table.name} table`,
parameters: {
type: 'object',
properties: table.columns.reduce((acc, col) => ({
...acc,
[col.name]: { type: col.type, description: col.description },
}), {}),
},
},
}));
}
```
### 3. Tool Chaining
Chain tool results:
```typescript
async function chatWithToolChaining(userMessage: string) {
let messages = [{ role: 'user', content: userMessage }];
while (true) {
const completion = await openai.chat.completions.create({
model: 'gpt-5',
messages,
tools,
});
const message = completion.choices[0].message;
messages.push(message);
if (!message.tool_calls) {
return message.content; // Final answer
}
// Execute tool calls and add results
for (const toolCall of message.tool_calls) {
const result = await executeFunction(
toolCall.function.name,
toolCall.function.arguments
);
messages.push({
role: 'tool',
tool_call_id: toolCall.id,
content: JSON.stringify(result),
});
}
}
}
```
### 4. Error Handling in Tools
```typescript
async function executeFunction(name: string, argsString: string) {
try {
const args = JSON.parse(argsString);
switch (name) {
case 'get_weather':
return await getWeather(args.location, args.unit);
default:
return { error: `Unknown function: ${name}` };
}
} catch (error: any) {
return { error: error.message };
}
}
```
### 5. Streaming with Tools
```typescript
const stream = await openai.chat.completions.create({
model: 'gpt-5',
messages,
tools,
stream: true,
});
for await (const chunk of stream) {
const delta = chunk.choices[0]?.delta;
// Check for tool calls in streaming
if (delta?.tool_calls) {
// Accumulate tool call data
console.log('Tool call chunk:', delta.tool_calls);
}
}
```
---
## Best Practices
**Schema Design**:
- Provide clear descriptions for each parameter
- Use enum when options are limited
- Mark required vs optional parameters
**Error Handling**:
- Return structured error objects
- Don't throw exceptions from tool functions
- Let the model handle error recovery
**Performance**:
- Execute independent tool calls in parallel
- Cache tool results when appropriate
- Limit recursion depth to avoid infinite loops
**Don't**:
- Expose sensitive internal functions
- Allow unlimited recursion
- Skip parameter validation
- Return unstructured error messages
---
**See Also**: Official Function Calling Guide (https://platform.openai.com/docs/guides/function-calling)

153
references/images-guide.md Normal file
View File

@@ -0,0 +1,153 @@
# Images Guide (DALL-E 3 & GPT-Image-1)
**Last Updated**: 2025-10-25
Best practices for image generation and editing with OpenAI's Images API.
---
## DALL-E 3 Generation
### Size Selection
| Size | Use Case |
|------|----------|
| 1024x1024 | Profile pictures, icons, square posts |
| 1024x1536 | Portrait photos, vertical ads |
| 1536x1024 | Landscape photos, banners |
| 1024x1792 | Tall portraits, mobile wallpapers |
| 1792x1024 | Wide banners, desktop wallpapers |
### Quality Settings
**standard**: Normal quality, faster, cheaper
- Use for: Prototyping, high-volume generation, quick iterations
**hd**: High definition, finer details, more expensive
- Use for: Final production images, marketing materials, print
### Style Options
**vivid**: Hyper-real, dramatic, high-contrast
- Use for: Marketing, advertising, eye-catching visuals
**natural**: More realistic, less dramatic
- Use for: Product photos, realistic scenes, professional content
---
## Prompting Best Practices
### Be Specific
```
❌ "A cat"
✅ "A white siamese cat with striking blue eyes, sitting on a wooden table, golden hour lighting, professional photography"
```
### Include Art Style
```
✅ "Oil painting of a sunset in the style of Claude Monet"
✅ "3D render of a futuristic city, Pixar animation style"
✅ "Professional product photo with studio lighting"
```
### Specify Lighting
```
- "Golden hour lighting"
- "Soft studio lighting from the left"
- "Dramatic shadows"
- "Bright natural daylight"
```
### Composition Details
```
- "Shallow depth of field"
- "Wide angle lens"
- "Centered composition"
- "Rule of thirds"
```
---
## GPT-Image-1 Editing
### Input Fidelity
**low**: More creative freedom
- Use for: Major transformations, style changes
**medium**: Balance (default)
- Use for: Most editing tasks
**high**: Stay close to original
- Use for: Subtle edits, preserving details
### Common Editing Tasks
1. **Background Removal**
```typescript
formData.append('prompt', 'Remove the background, keep only the product');
formData.append('format', 'png');
formData.append('background', 'transparent');
```
2. **Color Correction**
```typescript
formData.append('prompt', 'Increase brightness and saturation, make colors more vibrant');
```
3. **Object Removal**
```typescript
formData.append('prompt', 'Remove the person from the background');
```
4. **Compositing**
```typescript
formData.append('image', mainImage);
formData.append('image_2', logoImage);
formData.append('prompt', 'Add the logo to the product, as if stamped on the surface');
```
---
## Format Selection
| Format | Transparency | Compression | Best For |
|--------|--------------|-------------|----------|
| PNG | Yes | Lossless | Logos, transparency needed |
| JPEG | No | Lossy | Photos, smaller file size |
| WebP | Yes | Lossy | Web, best compression |
---
## Cost Optimization
1. Use standard quality unless HD is critical
2. Generate smaller sizes when possible
3. Cache generated images
4. Use natural style for most cases (vivid costs more)
5. Batch requests with delays to avoid rate limits
---
## Common Issues
### Prompt Revision
DALL-E 3 may revise prompts for safety/quality. Check `revised_prompt` in response.
### URL Expiration
Image URLs expire in 1 hour. Download and save if needed long-term.
### Non-Deterministic
Same prompt = different images. Cache results if consistency needed.
### Rate Limits
DALL-E has separate IPM (Images Per Minute) limits. Monitor and implement delays.
---
**See Also**: Official Images Guide (https://platform.openai.com/docs/guides/images)

311
references/models-guide.md Normal file
View File

@@ -0,0 +1,311 @@
# OpenAI Models Guide
**Last Updated**: 2025-10-25
This guide provides a comprehensive comparison of OpenAI's language models to help you choose the right model for your use case.
---
## GPT-5 Series (Released August 2025)
### gpt-5
**Status**: Latest flagship model
**Best for**: Complex reasoning, advanced problem-solving, code generation
**Key Features**:
- Advanced reasoning capabilities
- Unique parameters: `reasoning_effort`, `verbosity`
- Best-in-class performance on complex tasks
**Limitations**:
- ❌ No `temperature` support
- ❌ No `top_p` support
- ❌ No `logprobs` support
- ❌ CoT (Chain of Thought) does NOT persist between turns
**When to use**:
- Complex mathematical problems
- Advanced code generation
- Logic puzzles and reasoning tasks
- Multi-step problem solving
**Cost**: Highest pricing tier
---
### gpt-5-mini
**Status**: Cost-effective GPT-5 variant
**Best for**: Balanced performance and cost
**Key Features**:
- Same parameter support as gpt-5 (`reasoning_effort`, `verbosity`)
- Better than GPT-4 Turbo performance
- Significantly cheaper than gpt-5
**When to use**:
- Most production applications
- When you need GPT-5 features but not maximum performance
- High-volume use cases where cost matters
**Cost**: Mid-tier pricing
---
### gpt-5-nano
**Status**: Smallest GPT-5 variant
**Best for**: Simple tasks, high-volume processing
**Key Features**:
- Fastest response times
- Lowest cost in GPT-5 series
- Still supports GPT-5 unique parameters
**When to use**:
- Simple text generation
- High-volume batch processing
- Real-time streaming applications
- Cost-sensitive deployments
**Cost**: Low-tier pricing
---
## GPT-4o Series
### gpt-4o
**Status**: Multimodal flagship (pre-GPT-5)
**Best for**: Vision tasks, multimodal applications
**Key Features**:
- ✅ Vision support (image understanding)
- ✅ Temperature control
- ✅ Top-p sampling
- ✅ Function calling
- ✅ Structured outputs
**Limitations**:
- ❌ No `reasoning_effort` parameter
- ❌ No `verbosity` parameter
**When to use**:
- Image understanding and analysis
- OCR / text extraction from images
- Visual question answering
- When you need temperature/top_p control
- Multimodal applications
**Cost**: High-tier pricing (cheaper than gpt-5)
---
### gpt-4-turbo
**Status**: Fast GPT-4 variant
**Best for**: When you need GPT-4 speed
**Key Features**:
- Faster than base GPT-4
- Full parameter support (temperature, top_p, logprobs)
- Good balance of quality and speed
**When to use**:
- When GPT-4 quality is needed with faster responses
- Legacy applications requiring specific parameters
- When vision is not required
**Cost**: Mid-tier pricing
---
## Comparison Table
| Feature | GPT-5 | GPT-5-mini | GPT-5-nano | GPT-4o | GPT-4 Turbo |
|---------|-------|------------|------------|--------|-------------|
| **Reasoning** | Best | Excellent | Good | Excellent | Excellent |
| **Speed** | Medium | Medium | Fastest | Medium | Fast |
| **Cost** | Highest | Mid | Lowest | High | Mid |
| **reasoning_effort** | ✅ | ✅ | ✅ | ❌ | ❌ |
| **verbosity** | ✅ | ✅ | ✅ | ❌ | ❌ |
| **temperature** | ❌ | ❌ | ❌ | ✅ | ✅ |
| **top_p** | ❌ | ❌ | ❌ | ✅ | ✅ |
| **Vision** | ❌ | ❌ | ❌ | ✅ | ❌ |
| **Function calling** | ✅ | ✅ | ✅ | ✅ | ✅ |
| **Structured outputs** | ✅ | ✅ | ✅ | ✅ | ✅ |
| **Max output tokens** | 16,384 | 16,384 | 16,384 | 16,384 | 16,384 |
---
## Selection Guide
### Use GPT-5 when:
- ✅ You need the best reasoning performance
- ✅ Complex mathematical or logical problems
- ✅ Advanced code generation
- ✅ Multi-step problem solving
- ❌ Cost is not the primary concern
### Use GPT-5-mini when:
- ✅ You want GPT-5 features at lower cost
- ✅ Production applications with high volume
- ✅ Good reasoning performance is needed
- ✅ Balance of quality and cost matters
### Use GPT-5-nano when:
- ✅ Simple text generation tasks
- ✅ High-volume batch processing
- ✅ Real-time streaming applications
- ✅ Cost optimization is critical
- ❌ Complex reasoning is not required
### Use GPT-4o when:
- ✅ Vision / image understanding is required
- ✅ You need temperature/top_p control
- ✅ Multimodal applications
- ✅ OCR and visual analysis
- ❌ Pure text tasks (use GPT-5 series)
### Use GPT-4 Turbo when:
- ✅ Legacy application compatibility
- ✅ You need specific parameters not in GPT-5
- ✅ Fast responses without vision
- ❌ Not recommended for new applications (use GPT-5 or GPT-4o)
---
## Cost Optimization Strategies
### 1. Model Cascading
Start with cheaper models and escalate only when needed:
```
gpt-5-nano (try first) → gpt-5-mini → gpt-5 (if needed)
```
### 2. Task-Specific Model Selection
- **Simple**: Use gpt-5-nano
- **Medium complexity**: Use gpt-5-mini
- **Complex reasoning**: Use gpt-5
- **Vision tasks**: Use gpt-4o
### 3. Hybrid Approach
- Use embeddings (cheap) for retrieval
- Use gpt-5-mini for generation
- Use gpt-5 only for critical decisions
### 4. Batch Processing
- Use cheaper models for bulk operations
- Reserve expensive models for user-facing requests
---
## Parameter Guide
### GPT-5 Unique Parameters
**reasoning_effort**: Controls reasoning depth
- "minimal": Quick responses
- "low": Basic reasoning
- "medium": Balanced (default)
- "high": Deep reasoning for complex problems
**verbosity**: Controls output length
- "low": Concise responses
- "medium": Balanced detail (default)
- "high": Verbose, detailed responses
### GPT-4o/GPT-4 Turbo Parameters
**temperature**: Controls randomness (0-2)
- 0: Deterministic, focused
- 1: Balanced creativity (default)
- 2: Maximum creativity
**top_p**: Nucleus sampling (0-1)
- Lower values: More focused
- Higher values: More diverse
**logprobs**: Get token probabilities
- Useful for debugging and analysis
---
## Common Patterns
### Pattern 1: Automatic Model Selection
```typescript
function selectModel(taskComplexity: 'simple' | 'medium' | 'complex') {
switch (taskComplexity) {
case 'simple':
return 'gpt-5-nano';
case 'medium':
return 'gpt-5-mini';
case 'complex':
return 'gpt-5';
}
}
```
### Pattern 2: Fallback Chain
```typescript
async function completionWithFallback(prompt: string) {
const models = ['gpt-5-nano', 'gpt-5-mini', 'gpt-5'];
for (const model of models) {
try {
const result = await openai.chat.completions.create({
model,
messages: [{ role: 'user', content: prompt }],
});
// Validate quality
if (isGoodEnough(result)) {
return result;
}
} catch (error) {
continue;
}
}
throw new Error('All models failed');
}
```
### Pattern 3: Vision + Text Hybrid
```typescript
// Use gpt-4o for image analysis
const imageAnalysis = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [
{
role: 'user',
content: [
{ type: 'text', text: 'Describe this image' },
{ type: 'image_url', image_url: { url: imageUrl } },
],
},
],
});
// Use gpt-5 for reasoning based on analysis
const reasoning = await openai.chat.completions.create({
model: 'gpt-5',
messages: [
{ role: 'system', content: `Image analysis: ${imageAnalysis.choices[0].message.content}` },
{ role: 'user', content: 'What does this imply about...' },
],
});
```
---
## Official Documentation
- **GPT-5 Guide**: https://platform.openai.com/docs/guides/latest-model
- **Model Pricing**: https://openai.com/pricing
- **Model Comparison**: https://platform.openai.com/docs/models
---
**Summary**: Choose the right model based on your specific needs. GPT-5 series for reasoning, GPT-4o for vision, and optimize costs by selecting the smallest model that meets your requirements.

View File

@@ -0,0 +1,220 @@
# Structured Output Guide
**Last Updated**: 2025-10-25
Best practices for using JSON schemas with OpenAI's structured outputs feature.
---
## When to Use Structured Outputs
Use structured outputs when you need:
-**Guaranteed JSON format**: Response will always be valid JSON
-**Schema validation**: Enforce specific structure
-**Type safety**: Parse directly into TypeScript types
-**Data extraction**: Pull specific fields from text
-**Classification**: Map to predefined categories
---
## Schema Best Practices
### 1. Keep Schemas Simple
```typescript
// ✅ Good: Simple, focused schema
{
type: 'object',
properties: {
name: { type: 'string' },
age: { type: 'number' },
},
required: ['name', 'age'],
additionalProperties: false,
}
// ❌ Avoid: Overly complex nested structures
// (they work but are harder to debug)
```
### 2. Use Enums for Fixed Options
```typescript
{
type: 'object',
properties: {
category: {
type: 'string',
enum: ['bug', 'feature', 'question'],
},
priority: {
type: 'string',
enum: ['low', 'medium', 'high', 'critical'],
},
},
required: ['category', 'priority'],
}
```
### 3. Always Use `strict: true`
```typescript
response_format: {
type: 'json_schema',
json_schema: {
name: 'response_schema',
strict: true, // ✅ Enforces exact compliance
schema: { /* ... */ },
},
}
```
### 4. Set `additionalProperties: false`
```typescript
{
type: 'object',
properties: { /* ... */ },
required: [ /* ... */ ],
additionalProperties: false, // ✅ Prevents unexpected fields
}
```
---
## Common Use Cases
### Data Extraction
```typescript
const schema = {
type: 'object',
properties: {
person: { type: 'string' },
company: { type: 'string' },
email: { type: 'string' },
phone: { type: 'string' },
},
required: ['person'],
additionalProperties: false,
};
// Extract from unstructured text
const completion = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [
{ role: 'system', content: 'Extract contact information' },
{ role: 'user', content: 'John works at TechCorp, email: john@tech.com' },
],
response_format: { type: 'json_schema', json_schema: { name: 'contact', strict: true, schema } },
});
const contact = JSON.parse(completion.choices[0].message.content);
// { person: "John", company: "TechCorp", email: "john@tech.com", phone: null }
```
### Classification
```typescript
const schema = {
type: 'object',
properties: {
sentiment: { type: 'string', enum: ['positive', 'negative', 'neutral'] },
confidence: { type: 'number' },
topics: { type: 'array', items: { type: 'string' } },
},
required: ['sentiment', 'confidence', 'topics'],
additionalProperties: false,
};
// Classify text
const completion = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [
{ role: 'system', content: 'Classify the text' },
{ role: 'user', content: 'This product is amazing!' },
],
response_format: { type: 'json_schema', json_schema: { name: 'classification', strict: true, schema } },
});
const result = JSON.parse(completion.choices[0].message.content);
// { sentiment: "positive", confidence: 0.95, topics: ["product", "satisfaction"] }
```
---
## TypeScript Integration
### Type-Safe Parsing
```typescript
interface PersonProfile {
name: string;
age: number;
skills: string[];
}
const schema = {
type: 'object',
properties: {
name: { type: 'string' },
age: { type: 'number' },
skills: { type: 'array', items: { type: 'string' } },
},
required: ['name', 'age', 'skills'],
additionalProperties: false,
};
const completion = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [{ role: 'user', content: 'Generate a person profile' }],
response_format: { type: 'json_schema', json_schema: { name: 'person', strict: true, schema } },
});
const person: PersonProfile = JSON.parse(completion.choices[0].message.content);
// TypeScript knows the shape!
```
---
## Error Handling
```typescript
try {
const completion = await openai.chat.completions.create({
model: 'gpt-4o',
messages,
response_format: { type: 'json_schema', json_schema: { name: 'data', strict: true, schema } },
});
const data = JSON.parse(completion.choices[0].message.content);
return data;
} catch (error) {
if (error.message.includes('JSON')) {
console.error('Failed to parse JSON (should not happen with strict mode)');
}
throw error;
}
```
---
## Validation
While `strict: true` ensures the response matches the schema, you may want additional validation:
```typescript
import { z } from 'zod';
const zodSchema = z.object({
email: z.string().email(),
age: z.number().min(0).max(120),
});
const data = JSON.parse(completion.choices[0].message.content);
const validated = zodSchema.parse(data); // Throws if invalid
```
---
**See Also**: Official Structured Outputs Guide (https://platform.openai.com/docs/guides/structured-outputs)

453
references/top-errors.md Normal file
View File

@@ -0,0 +1,453 @@
# Top OpenAI API Errors & Solutions
**Last Updated**: 2025-10-25
**Skill**: openai-api
**Status**: Phase 1 Complete
---
## Overview
This document covers the 10 most common errors encountered when using OpenAI APIs, with causes, solutions, and code examples.
---
## 1. Rate Limit Error (429)
### Cause
Too many requests or tokens per minute/day.
### Error Response
```json
{
"error": {
"message": "Rate limit reached",
"type": "rate_limit_error",
"code": "rate_limit_exceeded"
}
}
```
### Solution
Implement exponential backoff:
```typescript
async function completionWithRetry(params, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await openai.chat.completions.create(params);
} catch (error: any) {
if (error.status === 429 && i < maxRetries - 1) {
const delay = Math.pow(2, i) * 1000; // 1s, 2s, 4s
console.log(`Rate limited. Retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
throw error;
}
}
}
```
---
## 2. Invalid API Key (401)
### Cause
Missing or incorrect `OPENAI_API_KEY`.
### Error Response
```json
{
"error": {
"message": "Incorrect API key provided",
"type": "invalid_request_error",
"code": "invalid_api_key"
}
}
```
### Solution
Verify environment variable:
```bash
# Check if set
echo $OPENAI_API_KEY
# Set in .env
OPENAI_API_KEY=sk-...
```
```typescript
if (!process.env.OPENAI_API_KEY) {
throw new Error('OPENAI_API_KEY environment variable is required');
}
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
```
---
## 3. Function Calling Schema Mismatch
### Cause
Tool definition doesn't match model expectations or arguments are invalid.
### Error Response
```json
{
"error": {
"message": "Invalid schema for function 'get_weather'",
"type": "invalid_request_error"
}
}
```
### Solution
Validate JSON schema:
```typescript
const tools = [
{
type: 'function',
function: {
name: 'get_weather',
description: 'Get weather for a location', // Required
parameters: { // Required
type: 'object',
properties: {
location: {
type: 'string',
description: 'City name' // Add descriptions
}
},
required: ['location'] // Specify required fields
}
}
}
];
```
---
## 4. Streaming Parse Error
### Cause
Incomplete or malformed SSE (Server-Sent Events) chunks.
### Symptom
```
SyntaxError: Unexpected end of JSON input
```
### Solution
Properly handle SSE format:
```typescript
const lines = chunk.split('\n').filter(line => line.trim() !== '');
for (const line of lines) {
if (line.startsWith('data: ')) {
const data = line.slice(6);
if (data === '[DONE]') {
break;
}
try {
const json = JSON.parse(data);
const content = json.choices[0]?.delta?.content || '';
console.log(content);
} catch (e) {
// Skip invalid JSON - don't crash
console.warn('Skipping invalid JSON chunk');
}
}
}
```
---
## 5. Vision Image Encoding Error
### Cause
Invalid base64 encoding or unsupported image format.
### Error Response
```json
{
"error": {
"message": "Invalid image format",
"type": "invalid_request_error"
}
}
```
### Solution
Ensure proper base64 encoding:
```typescript
import fs from 'fs';
// Read and encode image
const imageBuffer = fs.readFileSync('./image.jpg');
const base64Image = imageBuffer.toString('base64');
// Use with correct MIME type
const completion = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [
{
role: 'user',
content: [
{ type: 'text', text: 'What is in this image?' },
{
type: 'image_url',
image_url: {
url: `data:image/jpeg;base64,${base64Image}` // Include MIME type
}
}
]
}
]
});
```
---
## 6. Token Limit Exceeded
### Cause
Input + output tokens exceed model's context window.
### Error Response
```json
{
"error": {
"message": "This model's maximum context length is 128000 tokens",
"type": "invalid_request_error",
"code": "context_length_exceeded"
}
}
```
### Solution
Truncate input or reduce max_tokens:
```typescript
function truncateMessages(messages, maxTokens = 120000) {
// Rough estimate: 1 token ≈ 4 characters
const maxChars = maxTokens * 4;
let totalChars = 0;
const truncated = [];
for (const msg of messages.reverse()) {
const msgChars = msg.content.length;
if (totalChars + msgChars > maxChars) break;
truncated.unshift(msg);
totalChars += msgChars;
}
return truncated;
}
const completion = await openai.chat.completions.create({
model: 'gpt-5',
messages: truncateMessages(messages),
max_tokens: 8000, // Limit output tokens
});
```
---
## 7. GPT-5 Temperature Not Supported
### Cause
Using `temperature` parameter with GPT-5 models.
### Error Response
```json
{
"error": {
"message": "temperature is not supported for gpt-5",
"type": "invalid_request_error"
}
}
```
### Solution
Use `reasoning_effort` instead or switch to GPT-4o:
```typescript
// ❌ Bad - GPT-5 doesn't support temperature
const completion = await openai.chat.completions.create({
model: 'gpt-5',
messages: [...],
temperature: 0.7, // NOT SUPPORTED
});
// ✅ Good - Use reasoning_effort for GPT-5
const completion = await openai.chat.completions.create({
model: 'gpt-5',
messages: [...],
reasoning_effort: 'medium',
});
// ✅ Or use GPT-4o if you need temperature
const completion = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [...],
temperature: 0.7,
});
```
---
## 8. Streaming Not Closed Properly
### Cause
Stream not properly terminated, causing resource leaks.
### Symptom
Memory leaks, hanging connections.
### Solution
Always close streams:
```typescript
const stream = await openai.chat.completions.create({
model: 'gpt-5',
messages: [...],
stream: true,
});
try {
for await (const chunk of stream) {
const content = chunk.choices[0]?.delta?.content || '';
process.stdout.write(content);
}
} finally {
// Stream is automatically closed when iteration completes
// But handle errors explicitly
}
// For fetch-based streaming:
const reader = response.body?.getReader();
try {
while (true) {
const { done, value } = await reader!.read();
if (done) break;
// Process chunk
}
} finally {
reader!.releaseLock(); // Important!
}
```
---
## 9. API Key Exposure in Client-Side Code
### Cause
Including API key in frontend JavaScript.
### Risk
API key visible to all users, can be stolen and abused.
### Solution
Use server-side proxy:
```typescript
// ❌ Bad - Client-side (NEVER DO THIS)
const apiKey = 'sk-...'; // Exposed to all users!
const response = await fetch('https://api.openai.com/v1/chat/completions', {
headers: { 'Authorization': `Bearer ${apiKey}` }
});
// ✅ Good - Server-side proxy
// Frontend:
const response = await fetch('/api/chat', {
method: 'POST',
body: JSON.stringify({ message: 'Hello' }),
});
// Backend (e.g., Express):
app.post('/api/chat', async (req, res) => {
const completion = await openai.chat.completions.create({
model: 'gpt-5',
messages: [{ role: 'user', content: req.body.message }],
});
res.json(completion);
});
```
---
## 10. Embeddings Dimension Mismatch
### Cause
Using wrong dimensions for embedding model.
### Error Response
```json
{
"error": {
"message": "dimensions must be less than or equal to 3072 for text-embedding-3-large",
"type": "invalid_request_error"
}
}
```
### Solution
Use correct dimensions for each model:
```typescript
// text-embedding-3-small: default 1536, max 1536
const embedding1 = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: 'Hello world',
// dimensions: 256, // Optional: reduce from default 1536
});
// text-embedding-3-large: default 3072, max 3072
const embedding2 = await openai.embeddings.create({
model: 'text-embedding-3-large',
input: 'Hello world',
// dimensions: 1024, // Optional: reduce from default 3072
});
// text-embedding-ada-002: fixed 1536 (no dimensions parameter)
const embedding3 = await openai.embeddings.create({
model: 'text-embedding-ada-002',
input: 'Hello world',
// No dimensions parameter supported
});
```
---
## Quick Reference Table
| Error Code | HTTP Status | Primary Cause | Quick Fix |
|------------|-------------|---------------|-----------|
| `rate_limit_exceeded` | 429 | Too many requests | Exponential backoff |
| `invalid_api_key` | 401 | Wrong/missing key | Check OPENAI_API_KEY |
| `invalid_request_error` | 400 | Bad parameters | Validate schema/params |
| `context_length_exceeded` | 400 | Too many tokens | Truncate input |
| `model_not_found` | 404 | Invalid model name | Use correct model ID |
| `insufficient_quota` | 429 | No credits left | Add billing/credits |
---
## Additional Resources
- **Official Error Codes**: https://platform.openai.com/docs/guides/error-codes
- **Rate Limits Guide**: https://platform.openai.com/docs/guides/rate-limits
- **Best Practices**: https://platform.openai.com/docs/guides/production-best-practices
---
**Phase 1 Complete**
**Phase 2**: Additional errors for Embeddings, Images, Audio, Moderation (next session)

32
scripts/check-versions.sh Executable file
View File

@@ -0,0 +1,32 @@
#!/bin/bash
# Check OpenAI npm package versions
# Compares installed version with latest available
echo "Checking OpenAI API package versions..."
echo ""
packages=(
"openai"
)
for package in "${packages[@]}"; do
echo "📦 $package"
installed=$(npm list $package --depth=0 2>/dev/null | grep $package | awk '{print $2}' | sed 's/@//')
latest=$(npm view $package version 2>/dev/null)
if [ -z "$installed" ]; then
echo " Installed: NOT INSTALLED"
else
echo " Installed: $installed"
fi
echo " Latest: $latest"
if [ "$installed" != "$latest" ] && [ -n "$installed" ]; then
echo " ⚠️ Update available!"
fi
echo ""
done
echo "To update: npm install openai@latest"

View File

@@ -0,0 +1,229 @@
/**
* OpenAI Audio API - Whisper Transcription Examples
*
* This template demonstrates:
* - Basic audio transcription
* - Supported audio formats
* - Both SDK and fetch approaches
* - Error handling
*/
import OpenAI from 'openai';
import fs from 'fs';
import FormData from 'form-data';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
// =============================================================================
// BASIC TRANSCRIPTION (SDK)
// =============================================================================
async function basicTranscription() {
const transcription = await openai.audio.transcriptions.create({
file: fs.createReadStream('./audio.mp3'),
model: 'whisper-1',
});
console.log('Transcription:', transcription.text);
return transcription.text;
}
// =============================================================================
// TRANSCRIPTION WITH FETCH
// =============================================================================
async function transcriptionFetch() {
const formData = new FormData();
formData.append('file', fs.createReadStream('./audio.mp3'));
formData.append('model', 'whisper-1');
const response = await fetch('https://api.openai.com/v1/audio/transcriptions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`,
...formData.getHeaders(),
},
body: formData,
});
const data: any = await response.json();
console.log('Transcription:', data.text);
return data.text;
}
// =============================================================================
// MULTIPLE AUDIO FORMATS
// =============================================================================
async function multipleFormats() {
const formats = ['mp3', 'wav', 'm4a', 'webm'];
for (const format of formats) {
const filename = `./audio.${format}`;
if (fs.existsSync(filename)) {
console.log(`Transcribing ${format}...`);
const transcription = await openai.audio.transcriptions.create({
file: fs.createReadStream(filename),
model: 'whisper-1',
});
console.log(`${format.toUpperCase()}: ${transcription.text}`);
} else {
console.log(`${filename} not found, skipping...`);
}
}
}
// =============================================================================
// ERROR HANDLING
// =============================================================================
async function withErrorHandling(audioFilePath: string) {
try {
// Check if file exists
if (!fs.existsSync(audioFilePath)) {
throw new Error(`Audio file not found: ${audioFilePath}`);
}
// Check file size (Whisper has limits)
const stats = fs.statSync(audioFilePath);
const fileSizeMB = stats.size / (1024 * 1024);
console.log(`File size: ${fileSizeMB.toFixed(2)} MB`);
if (fileSizeMB > 25) {
console.warn('Warning: File larger than 25MB may be rejected');
}
// Transcribe
const transcription = await openai.audio.transcriptions.create({
file: fs.createReadStream(audioFilePath),
model: 'whisper-1',
});
return transcription.text;
} catch (error: any) {
if (error.message.includes('file not found')) {
console.error('Audio file not found');
} else if (error.message.includes('file too large')) {
console.error('Audio file exceeds size limit');
} else if (error.message.includes('unsupported format')) {
console.error('Audio format not supported');
} else {
console.error('Transcription error:', error.message);
}
throw error;
}
}
// =============================================================================
// BATCH TRANSCRIPTION
// =============================================================================
async function batchTranscription(audioFiles: string[]) {
const results = [];
for (const filePath of audioFiles) {
console.log(`Transcribing: ${filePath}`);
try {
const transcription = await openai.audio.transcriptions.create({
file: fs.createReadStream(filePath),
model: 'whisper-1',
});
results.push({
file: filePath,
text: transcription.text,
success: true,
});
console.log(`${filePath}: ${transcription.text.substring(0, 50)}...`);
} catch (error: any) {
results.push({
file: filePath,
error: error.message,
success: false,
});
console.error(`${filePath}: ${error.message}`);
}
// Wait 1 second between requests to avoid rate limits
await new Promise(resolve => setTimeout(resolve, 1000));
}
console.log(`\nCompleted: ${results.filter(r => r.success).length}/${results.length}`);
return results;
}
// =============================================================================
// SAVE TRANSCRIPTION TO FILE
// =============================================================================
async function transcribeAndSave(audioFilePath: string, outputFilePath: string) {
const transcription = await openai.audio.transcriptions.create({
file: fs.createReadStream(audioFilePath),
model: 'whisper-1',
});
fs.writeFileSync(outputFilePath, transcription.text);
console.log(`Transcription saved to: ${outputFilePath}`);
console.log(`Content: ${transcription.text}`);
return transcription.text;
}
// =============================================================================
// MAIN EXECUTION
// =============================================================================
async function main() {
console.log('=== OpenAI Whisper Transcription Examples ===\n');
console.log('Note: This script requires audio files to run.');
console.log('Supported formats: mp3, mp4, mpeg, mpga, m4a, wav, webm\n');
// Example 1: Basic transcription (uncomment when you have audio.mp3)
// console.log('1. Basic Transcription:');
// await basicTranscription();
// console.log();
// Example 2: Transcription with fetch
// console.log('2. Transcription with Fetch:');
// await transcriptionFetch();
// console.log();
// Example 3: Multiple formats
// console.log('3. Multiple Formats:');
// await multipleFormats();
// console.log();
// Example 4: Save to file
// console.log('4. Transcribe and Save:');
// await transcribeAndSave('./audio.mp3', './transcription.txt');
// console.log();
}
// Run if executed directly
if (require.main === module) {
main().catch(console.error);
}
export {
basicTranscription,
transcriptionFetch,
multipleFormats,
withErrorHandling,
batchTranscription,
transcribeAndSave,
};

View File

@@ -0,0 +1,24 @@
// Basic Chat Completion with GPT-5
// Simple example showing the minimal setup for chat completions
import OpenAI from 'openai';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
async function basicChatCompletion() {
const completion = await openai.chat.completions.create({
model: 'gpt-5',
messages: [
{
role: 'user',
content: 'What are the three laws of robotics?'
}
],
});
console.log(completion.choices[0].message.content);
}
basicChatCompletion();

View File

@@ -0,0 +1,73 @@
// Complete Chat Completion Example (Node.js SDK)
// Shows multi-turn conversation, GPT-5 parameters, and error handling
import OpenAI from 'openai';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
async function chatWithGPT5() {
try {
// Multi-turn conversation
const messages: OpenAI.Chat.ChatCompletionMessageParam[] = [
{
role: 'system',
content: 'You are a helpful assistant that explains complex topics simply.'
},
{
role: 'user',
content: 'Explain quantum computing to a 10-year-old'
}
];
// First turn with GPT-5 specific parameters
const completion1 = await openai.chat.completions.create({
model: 'gpt-5',
messages: messages,
reasoning_effort: 'medium', // GPT-5 parameter
verbosity: 'high', // GPT-5 parameter
max_tokens: 500,
});
const assistantMessage = completion1.choices[0].message;
console.log('Assistant:', assistantMessage.content);
// Add assistant response to conversation
messages.push(assistantMessage);
// Follow-up question
messages.push({
role: 'user',
content: 'Can you give me an example?'
});
// Second turn
const completion2 = await openai.chat.completions.create({
model: 'gpt-5',
messages: messages,
reasoning_effort: 'medium',
verbosity: 'medium',
max_tokens: 300,
});
console.log('Assistant:', completion2.choices[0].message.content);
// Token usage
console.log('\nToken usage:');
console.log('- Prompt tokens:', completion2.usage?.prompt_tokens);
console.log('- Completion tokens:', completion2.usage?.completion_tokens);
console.log('- Total tokens:', completion2.usage?.total_tokens);
} catch (error: any) {
if (error.status === 401) {
console.error('Invalid API key. Check OPENAI_API_KEY environment variable.');
} else if (error.status === 429) {
console.error('Rate limit exceeded. Please wait and try again.');
} else {
console.error('Error:', error.message);
}
}
}
chatWithGPT5();

View File

@@ -0,0 +1,101 @@
// Complete Cloudflare Worker with OpenAI Integration
// Supports both streaming and non-streaming chat completions
interface Env {
OPENAI_API_KEY: string;
}
interface ChatRequest {
message: string;
stream?: boolean;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
// CORS headers
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type',
};
// Handle CORS preflight
if (request.method === 'OPTIONS') {
return new Response(null, { headers: corsHeaders });
}
if (request.method !== 'POST') {
return new Response('Method not allowed', { status: 405 });
}
try {
const { message, stream } = await request.json() as ChatRequest;
if (!message) {
return new Response(
JSON.stringify({ error: 'Message is required' }),
{ status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
);
}
// Call OpenAI
const openaiResponse = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${env.OPENAI_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'gpt-5',
messages: [
{ role: 'user', content: message }
],
stream: stream || false,
reasoning_effort: 'medium',
max_tokens: 500,
}),
});
if (!openaiResponse.ok) {
const error = await openaiResponse.text();
return new Response(
JSON.stringify({ error: `OpenAI API error: ${error}` }),
{ status: openaiResponse.status, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
);
}
// Streaming response
if (stream) {
return new Response(openaiResponse.body, {
headers: {
...corsHeaders,
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
},
});
}
// Non-streaming response
const data = await openaiResponse.json();
return new Response(
JSON.stringify({
response: data.choices[0].message.content,
usage: data.usage,
}),
{
headers: {
...corsHeaders,
'Content-Type': 'application/json',
},
}
);
} catch (error: any) {
return new Response(
JSON.stringify({ error: error.message || 'Internal server error' }),
{ status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
);
}
},
};

267
templates/embeddings.ts Normal file
View File

@@ -0,0 +1,267 @@
/**
* OpenAI Embeddings API - Complete Examples
*
* This template demonstrates:
* - Basic embeddings generation
* - Custom dimensions for storage optimization
* - Batch processing multiple texts
* - RAG (Retrieval-Augmented Generation) pattern
* - Cosine similarity for semantic search
*/
import OpenAI from 'openai';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
// =============================================================================
// BASIC EMBEDDINGS
// =============================================================================
async function basicEmbedding() {
const embedding = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: 'The food was delicious and the waiter was friendly.',
});
console.log('Embedding dimensions:', embedding.data[0].embedding.length);
console.log('First 5 values:', embedding.data[0].embedding.slice(0, 5));
console.log('Token usage:', embedding.usage);
return embedding.data[0].embedding;
}
// =============================================================================
// CUSTOM DIMENSIONS (Storage Optimization)
// =============================================================================
async function customDimensions() {
// Default: 1536 dimensions
const fullEmbedding = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: 'Sample text',
});
console.log('Full dimensions:', fullEmbedding.data[0].embedding.length);
// Reduced: 256 dimensions (6x storage reduction)
const reducedEmbedding = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: 'Sample text',
dimensions: 256,
});
console.log('Reduced dimensions:', reducedEmbedding.data[0].embedding.length);
return reducedEmbedding.data[0].embedding;
}
// =============================================================================
// BATCH PROCESSING
// =============================================================================
async function batchEmbeddings() {
const texts = [
'First document about TypeScript',
'Second document about Python',
'Third document about JavaScript',
];
const response = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: texts,
dimensions: 512, // Optional: reduce dimensions
});
// Process results
const embeddings = response.data.map((item, index) => ({
text: texts[index],
embedding: item.embedding,
}));
console.log(`Generated ${embeddings.length} embeddings`);
console.log('Total tokens used:', response.usage.total_tokens);
return embeddings;
}
// =============================================================================
// COSINE SIMILARITY
// =============================================================================
function cosineSimilarity(a: number[], b: number[]): number {
const dotProduct = a.reduce((sum, val, i) => sum + val * b[i], 0);
const magnitudeA = Math.sqrt(a.reduce((sum, val) => sum + val * val, 0));
const magnitudeB = Math.sqrt(b.reduce((sum, val) => sum + val * val, 0));
return dotProduct / (magnitudeA * magnitudeB);
}
// =============================================================================
// L2 NORMALIZATION
// =============================================================================
function normalizeL2(vector: number[]): number[] {
const magnitude = Math.sqrt(vector.reduce((sum, val) => sum + val * val, 0));
return vector.map(val => val / magnitude);
}
// =============================================================================
// SEMANTIC SEARCH
// =============================================================================
interface Document {
text: string;
embedding: number[];
}
async function semanticSearch(query: string, documents: Document[]) {
// Embed the query
const queryEmbedding = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: query,
});
const queryVector = queryEmbedding.data[0].embedding;
// Calculate similarity scores
const results = documents.map(doc => ({
text: doc.text,
similarity: cosineSimilarity(queryVector, doc.embedding),
}));
// Sort by similarity (highest first)
results.sort((a, b) => b.similarity - a.similarity);
return results;
}
// =============================================================================
// RAG (Retrieval-Augmented Generation)
// =============================================================================
async function ragExample() {
// 1. Create knowledge base
const knowledgeBase = [
'TypeScript is a superset of JavaScript that adds static typing.',
'Python is a high-level programming language known for readability.',
'React is a JavaScript library for building user interfaces.',
'Node.js is a JavaScript runtime built on Chrome\'s V8 engine.',
];
// 2. Generate embeddings for knowledge base
const embeddingsResponse = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: knowledgeBase,
});
const documents: Document[] = knowledgeBase.map((text, index) => ({
text,
embedding: embeddingsResponse.data[index].embedding,
}));
// 3. User query
const userQuery = 'What is TypeScript?';
// 4. Find relevant documents
const searchResults = await semanticSearch(userQuery, documents);
const topResults = searchResults.slice(0, 2); // Top 2 most relevant
console.log('Most relevant documents:');
topResults.forEach(result => {
console.log(`- [${result.similarity.toFixed(3)}] ${result.text}`);
});
// 5. Generate answer using retrieved context
const context = topResults.map(r => r.text).join('\n\n');
const completion = await openai.chat.completions.create({
model: 'gpt-5',
messages: [
{
role: 'system',
content: `Answer the question using the following context:\n\n${context}`,
},
{
role: 'user',
content: userQuery,
},
],
});
console.log('\nAnswer:', completion.choices[0].message.content);
return completion.choices[0].message.content;
}
// =============================================================================
// DIMENSION REDUCTION (Post-Generation)
// =============================================================================
async function manualDimensionReduction() {
// Get full embedding
const response = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: 'Testing 123',
});
const fullEmbedding = response.data[0].embedding;
console.log('Full dimensions:', fullEmbedding.length);
// Truncate to 256 dimensions
const truncated = fullEmbedding.slice(0, 256);
console.log('Truncated dimensions:', truncated.length);
// Normalize (recommended after truncation)
const normalized = normalizeL2(truncated);
return normalized;
}
// =============================================================================
// MAIN EXECUTION
// =============================================================================
async function main() {
console.log('=== OpenAI Embeddings Examples ===\n');
// Example 1: Basic embedding
console.log('1. Basic Embedding:');
await basicEmbedding();
console.log();
// Example 2: Custom dimensions
console.log('2. Custom Dimensions:');
await customDimensions();
console.log();
// Example 3: Batch processing
console.log('3. Batch Processing:');
await batchEmbeddings();
console.log();
// Example 4: RAG pattern
console.log('4. RAG (Retrieval-Augmented Generation):');
await ragExample();
console.log();
// Example 5: Manual dimension reduction
console.log('5. Manual Dimension Reduction:');
await manualDimensionReduction();
console.log();
}
// Run if executed directly
if (require.main === module) {
main().catch(console.error);
}
export {
basicEmbedding,
customDimensions,
batchEmbeddings,
semanticSearch,
ragExample,
cosineSimilarity,
normalizeL2,
};

View File

@@ -0,0 +1,151 @@
// Function Calling (Tool Use) with GPT-5
// Complete example showing tool definition, execution, and multi-turn flow
import OpenAI from 'openai';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
// Define available tools/functions
const tools: OpenAI.Chat.ChatCompletionTool[] = [
{
type: 'function',
function: {
name: 'get_weather',
description: 'Get the current weather for a location',
parameters: {
type: 'object',
properties: {
location: {
type: 'string',
description: 'The city name, e.g., San Francisco'
},
unit: {
type: 'string',
enum: ['celsius', 'fahrenheit'],
description: 'Temperature unit'
}
},
required: ['location']
}
}
},
{
type: 'function',
function: {
name: 'search_web',
description: 'Search the web for information',
parameters: {
type: 'object',
properties: {
query: {
type: 'string',
description: 'The search query'
}
},
required: ['query']
}
}
}
];
// Implement the actual functions
async function getWeather(location: string, unit: string = 'fahrenheit'): Promise<string> {
// In production, call a real weather API
return JSON.stringify({
location,
temperature: 72,
unit,
condition: 'sunny',
forecast: 'Clear skies throughout the day'
});
}
async function searchWeb(query: string): Promise<string> {
// In production, call a real search API
return JSON.stringify({
query,
results: [
{ title: 'Example Result 1', snippet: 'This is a sample search result...' },
{ title: 'Example Result 2', snippet: 'Another sample result...' }
]
});
}
// Execute function based on name
async function executeFunction(name: string, argumentsJson: string): Promise<string> {
const args = JSON.parse(argumentsJson);
switch (name) {
case 'get_weather':
return await getWeather(args.location, args.unit);
case 'search_web':
return await searchWeb(args.query);
default:
throw new Error(`Unknown function: ${name}`);
}
}
async function chatWithTools(userMessage: string) {
const messages: OpenAI.Chat.ChatCompletionMessageParam[] = [
{
role: 'user',
content: userMessage
}
];
console.log('User:', userMessage);
// Keep looping until model doesn't call any tools
while (true) {
const completion = await openai.chat.completions.create({
model: 'gpt-5',
messages: messages,
tools: tools,
});
const message = completion.choices[0].message;
messages.push(message);
// If no tool calls, we're done
if (!message.tool_calls) {
console.log('Assistant:', message.content);
return message.content;
}
// Execute all tool calls
console.log(`\nCalling ${message.tool_calls.length} tool(s)...`);
for (const toolCall of message.tool_calls) {
console.log(`- ${toolCall.function.name}(${toolCall.function.arguments})`);
const result = await executeFunction(
toolCall.function.name,
toolCall.function.arguments
);
console.log(` Result: ${result}`);
// Add tool result to conversation
messages.push({
role: 'tool',
tool_call_id: toolCall.id,
content: result
});
}
console.log('\nModel processing tool results...\n');
}
}
// Example usage
async function main() {
await chatWithTools('What is the weather in San Francisco in celsius?');
console.log('\n---\n');
await chatWithTools('Search for the latest TypeScript features');
}
main();

336
templates/image-editing.ts Normal file
View File

@@ -0,0 +1,336 @@
/**
* OpenAI Images API - Image Editing Examples (GPT-Image-1)
*
* This template demonstrates:
* - Basic image editing
* - Compositing multiple images
* - Transparent backgrounds
* - Different output formats
* - Compression settings
*
* NOTE: Image editing uses multipart/form-data, not JSON
*/
import fs from 'fs';
import FormData from 'form-data';
const OPENAI_API_KEY = process.env.OPENAI_API_KEY;
// =============================================================================
// BASIC IMAGE EDITING
// =============================================================================
async function basicEdit() {
const formData = new FormData();
formData.append('model', 'gpt-image-1');
formData.append('image', fs.createReadStream('./input-image.jpg'));
formData.append('prompt', 'Change the sky to a sunset with orange and pink colors');
formData.append('size', '1024x1024');
const response = await fetch('https://api.openai.com/v1/images/edits', {
method: 'POST',
headers: {
'Authorization': `Bearer ${OPENAI_API_KEY}`,
...formData.getHeaders(),
},
body: formData,
});
const data: any = await response.json();
console.log('Edited image URL:', data.data[0].url);
return data.data[0].url;
}
// =============================================================================
// COMPOSITE TWO IMAGES
// =============================================================================
async function compositeImages() {
const formData = new FormData();
formData.append('model', 'gpt-image-1');
formData.append('image', fs.createReadStream('./woman.jpg'));
formData.append('image_2', fs.createReadStream('./logo.png'));
formData.append('prompt', 'Add the logo to the woman\'s top, as if stamped into the fabric.');
formData.append('input_fidelity', 'high'); // Stay close to original
formData.append('size', '1024x1024');
const response = await fetch('https://api.openai.com/v1/images/edits', {
method: 'POST',
headers: {
'Authorization': `Bearer ${OPENAI_API_KEY}`,
...formData.getHeaders(),
},
body: formData,
});
const data: any = await response.json();
console.log('Composite image URL:', data.data[0].url);
return data.data[0].url;
}
// =============================================================================
// REMOVE BACKGROUND (Transparent)
// =============================================================================
async function removeBackground() {
const formData = new FormData();
formData.append('model', 'gpt-image-1');
formData.append('image', fs.createReadStream('./product.jpg'));
formData.append('prompt', 'Remove the background, keeping only the product.');
formData.append('format', 'png'); // Required for transparency
formData.append('background', 'transparent');
formData.append('size', '1024x1024');
const response = await fetch('https://api.openai.com/v1/images/edits', {
method: 'POST',
headers: {
'Authorization': `Bearer ${OPENAI_API_KEY}`,
...formData.getHeaders(),
},
body: formData,
});
const data: any = await response.json();
console.log('Transparent background URL:', data.data[0].url);
// Download and save
const imageResponse = await fetch(data.data[0].url);
const buffer = Buffer.from(await imageResponse.arrayBuffer());
fs.writeFileSync('product-no-bg.png', buffer);
console.log('Saved to: product-no-bg.png');
return data.data[0].url;
}
// =============================================================================
// INPUT FIDELITY OPTIONS
// =============================================================================
async function fidelityComparison() {
const baseFormData = () => {
const formData = new FormData();
formData.append('model', 'gpt-image-1');
formData.append('image', fs.createReadStream('./portrait.jpg'));
formData.append('prompt', 'Add sunglasses to the person');
return formData;
};
// Low fidelity (more creative freedom)
const lowFidelity = baseFormData();
lowFidelity.append('input_fidelity', 'low');
const lowResponse = await fetch('https://api.openai.com/v1/images/edits', {
method: 'POST',
headers: {
'Authorization': `Bearer ${OPENAI_API_KEY}`,
...lowFidelity.getHeaders(),
},
body: lowFidelity,
});
const lowData: any = await lowResponse.json();
console.log('Low fidelity URL:', lowData.data[0].url);
// High fidelity (stay closer to original)
const highFidelity = baseFormData();
highFidelity.append('input_fidelity', 'high');
const highResponse = await fetch('https://api.openai.com/v1/images/edits', {
method: 'POST',
headers: {
'Authorization': `Bearer ${OPENAI_API_KEY}`,
...highFidelity.getHeaders(),
},
body: highFidelity,
});
const highData: any = await highResponse.json();
console.log('High fidelity URL:', highData.data[0].url);
return { low: lowData.data[0].url, high: highData.data[0].url };
}
// =============================================================================
// OUTPUT FORMATS AND COMPRESSION
// =============================================================================
async function formatComparison() {
const basePrompt = 'Add a blue sky to the background';
// PNG (supports transparency, larger file)
const pngFormData = new FormData();
pngFormData.append('model', 'gpt-image-1');
pngFormData.append('image', fs.createReadStream('./scene.jpg'));
pngFormData.append('prompt', basePrompt);
pngFormData.append('format', 'png');
const pngResponse = await fetch('https://api.openai.com/v1/images/edits', {
method: 'POST',
headers: {
'Authorization': `Bearer ${OPENAI_API_KEY}`,
...pngFormData.getHeaders(),
},
body: pngFormData,
});
const pngData: any = await pngResponse.json();
console.log('PNG format URL:', pngData.data[0].url);
// JPEG (smaller file, no transparency)
const jpegFormData = new FormData();
jpegFormData.append('model', 'gpt-image-1');
jpegFormData.append('image', fs.createReadStream('./scene.jpg'));
jpegFormData.append('prompt', basePrompt);
jpegFormData.append('format', 'jpeg');
jpegFormData.append('output_compression', '80'); // 0-100
const jpegResponse = await fetch('https://api.openai.com/v1/images/edits', {
method: 'POST',
headers: {
'Authorization': `Bearer ${OPENAI_API_KEY}`,
...jpegFormData.getHeaders(),
},
body: jpegFormData,
});
const jpegData: any = await jpegResponse.json();
console.log('JPEG format URL:', jpegData.data[0].url);
// WebP (best compression, supports transparency)
const webpFormData = new FormData();
webpFormData.append('model', 'gpt-image-1');
webpFormData.append('image', fs.createReadStream('./scene.jpg'));
webpFormData.append('prompt', basePrompt);
webpFormData.append('format', 'webp');
webpFormData.append('output_compression', '85');
const webpResponse = await fetch('https://api.openai.com/v1/images/edits', {
method: 'POST',
headers: {
'Authorization': `Bearer ${OPENAI_API_KEY}`,
...webpFormData.getHeaders(),
},
body: webpFormData,
});
const webpData: any = await webpResponse.json();
console.log('WebP format URL:', webpData.data[0].url);
return { png: pngData.data[0].url, jpeg: jpegData.data[0].url, webp: webpData.data[0].url };
}
// =============================================================================
// COMMON EDITING TASKS
// =============================================================================
async function commonEdits() {
// 1. Color correction
const colorCorrect = new FormData();
colorCorrect.append('model', 'gpt-image-1');
colorCorrect.append('image', fs.createReadStream('./photo.jpg'));
colorCorrect.append('prompt', 'Increase brightness and saturation, make colors more vibrant');
// 2. Object removal
const objectRemoval = new FormData();
objectRemoval.append('model', 'gpt-image-1');
objectRemoval.append('image', fs.createReadStream('./scene.jpg'));
objectRemoval.append('prompt', 'Remove the person from the background');
// 3. Style transfer
const styleTransfer = new FormData();
styleTransfer.append('model', 'gpt-image-1');
styleTransfer.append('image', fs.createReadStream('./photo.jpg'));
styleTransfer.append('prompt', 'Transform this photo into a watercolor painting style');
// 4. Add text/overlay
const addText = new FormData();
addText.append('model', 'gpt-image-1');
addText.append('image', fs.createReadStream('./poster.jpg'));
addText.append('prompt', 'Add the text "SALE" in large bold letters at the top');
console.log('Common editing tasks prepared');
return { colorCorrect, objectRemoval, styleTransfer, addText };
}
// =============================================================================
// ERROR HANDLING
// =============================================================================
async function withErrorHandling() {
try {
const formData = new FormData();
formData.append('model', 'gpt-image-1');
formData.append('image', fs.createReadStream('./input.jpg'));
formData.append('prompt', 'Edit the image');
const response = await fetch('https://api.openai.com/v1/images/edits', {
method: 'POST',
headers: {
'Authorization': `Bearer ${OPENAI_API_KEY}`,
...formData.getHeaders(),
},
body: formData,
});
if (!response.ok) {
const error = await response.json();
throw new Error(`API error: ${error.error?.message}`);
}
const data: any = await response.json();
return data.data[0].url;
} catch (error: any) {
if (error.message.includes('file not found')) {
console.error('Input image file not found');
} else if (error.message.includes('rate limit')) {
console.error('Rate limit exceeded - wait and retry');
} else {
console.error('Unexpected error:', error.message);
}
throw error;
}
}
// =============================================================================
// MAIN EXECUTION
// =============================================================================
async function main() {
console.log('=== OpenAI Image Editing (GPT-Image-1) Examples ===\n');
console.log('Note: This script requires input images to run.');
console.log('Create test images first or modify the file paths.\n');
// Uncomment the examples you want to run:
// console.log('1. Basic Edit:');
// await basicEdit();
// console.log();
// console.log('2. Composite Images:');
// await compositeImages();
// console.log();
// console.log('3. Remove Background:');
// await removeBackground();
// console.log();
}
// Run if executed directly
if (require.main === module) {
main().catch(console.error);
}
export {
basicEdit,
compositeImages,
removeBackground,
fidelityComparison,
formatComparison,
commonEdits,
withErrorHandling,
};

View File

@@ -0,0 +1,349 @@
/**
* OpenAI Images API - DALL-E 3 Generation Examples
*
* This template demonstrates:
* - Basic image generation
* - Quality settings (standard vs HD)
* - Style options (vivid vs natural)
* - Different sizes and formats
* - Base64 output
* - Saving images to disk
*/
import OpenAI from 'openai';
import fs from 'fs';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
// =============================================================================
// BASIC IMAGE GENERATION
// =============================================================================
async function basicGeneration() {
const image = await openai.images.generate({
model: 'dall-e-3',
prompt: 'A white siamese cat with striking blue eyes',
size: '1024x1024',
quality: 'standard',
style: 'vivid',
n: 1,
});
console.log('Generated image URL:', image.data[0].url);
console.log('Revised prompt:', image.data[0].revised_prompt);
return image.data[0].url;
}
// =============================================================================
// QUALITY COMPARISON
// =============================================================================
async function qualityComparison() {
const prompt = 'A futuristic city at sunset with flying cars';
// Standard quality (faster, cheaper)
console.log('Generating standard quality image...');
const standard = await openai.images.generate({
model: 'dall-e-3',
prompt,
quality: 'standard',
});
console.log('Standard quality URL:', standard.data[0].url);
// HD quality (finer details, more expensive)
console.log('Generating HD quality image...');
const hd = await openai.images.generate({
model: 'dall-e-3',
prompt,
quality: 'hd',
});
console.log('HD quality URL:', hd.data[0].url);
return { standard: standard.data[0].url, hd: hd.data[0].url };
}
// =============================================================================
// STYLE COMPARISON
// =============================================================================
async function styleComparison() {
const prompt = 'A mountain landscape with a lake';
// Vivid style (hyper-real, dramatic)
console.log('Generating vivid style image...');
const vivid = await openai.images.generate({
model: 'dall-e-3',
prompt,
style: 'vivid',
});
console.log('Vivid style URL:', vivid.data[0].url);
// Natural style (more realistic, less dramatic)
console.log('Generating natural style image...');
const natural = await openai.images.generate({
model: 'dall-e-3',
prompt,
style: 'natural',
});
console.log('Natural style URL:', natural.data[0].url);
return { vivid: vivid.data[0].url, natural: natural.data[0].url };
}
// =============================================================================
// DIFFERENT SIZES
// =============================================================================
async function differentSizes() {
const prompt = 'A minimalist logo for a tech company';
// Square
const square = await openai.images.generate({
model: 'dall-e-3',
prompt,
size: '1024x1024',
});
console.log('Square (1024x1024):', square.data[0].url);
// Portrait
const portrait = await openai.images.generate({
model: 'dall-e-3',
prompt,
size: '1024x1792',
});
console.log('Portrait (1024x1792):', portrait.data[0].url);
// Landscape
const landscape = await openai.images.generate({
model: 'dall-e-3',
prompt,
size: '1792x1024',
});
console.log('Landscape (1792x1024):', landscape.data[0].url);
return { square, portrait, landscape };
}
// =============================================================================
// BASE64 OUTPUT
// =============================================================================
async function base64Output() {
const image = await openai.images.generate({
model: 'dall-e-3',
prompt: 'A cyberpunk street scene at night',
response_format: 'b64_json',
});
const base64Data = image.data[0].b64_json;
console.log('Base64 data length:', base64Data?.length);
console.log('First 100 chars:', base64Data?.substring(0, 100));
// Convert to buffer and save
if (base64Data) {
const buffer = Buffer.from(base64Data, 'base64');
fs.writeFileSync('generated-image.png', buffer);
console.log('Image saved to: generated-image.png');
}
return base64Data;
}
// =============================================================================
// DOWNLOAD AND SAVE IMAGE
// =============================================================================
async function downloadAndSave(url: string, filename: string) {
const response = await fetch(url);
const arrayBuffer = await response.arrayBuffer();
const buffer = Buffer.from(arrayBuffer);
fs.writeFileSync(filename, buffer);
console.log(`Image saved to: ${filename}`);
}
async function generateAndSave() {
const image = await openai.images.generate({
model: 'dall-e-3',
prompt: 'A serene Japanese garden with cherry blossoms',
size: '1024x1024',
quality: 'hd',
style: 'natural',
});
const url = image.data[0].url;
await downloadAndSave(url, 'japanese-garden.png');
return url;
}
// =============================================================================
// DETAILED PROMPT EXAMPLES
// =============================================================================
async function detailedPrompts() {
// Example 1: Specific art style
const artStyle = await openai.images.generate({
model: 'dall-e-3',
prompt: 'An oil painting of a sunset over the ocean in the style of Claude Monet',
style: 'natural',
});
console.log('Art style result:', artStyle.data[0].url);
// Example 2: Detailed composition
const detailed = await openai.images.generate({
model: 'dall-e-3',
prompt: 'A professional product photo of a smartwatch on a white marble surface, with soft studio lighting from the left, shallow depth of field, commercial photography style',
quality: 'hd',
style: 'natural',
});
console.log('Detailed composition:', detailed.data[0].url);
// Example 3: Character design
const character = await openai.images.generate({
model: 'dall-e-3',
prompt: 'A friendly robot character with round edges, bright blue and white colors, large expressive eyes, modern minimalist design, 3D render style',
style: 'vivid',
});
console.log('Character design:', character.data[0].url);
return { artStyle, detailed, character };
}
// =============================================================================
// ERROR HANDLING
// =============================================================================
async function withErrorHandling() {
try {
const image = await openai.images.generate({
model: 'dall-e-3',
prompt: 'A beautiful landscape',
});
return image.data[0].url;
} catch (error: any) {
if (error.status === 400) {
console.error('Bad request - check your prompt for policy violations');
} else if (error.status === 401) {
console.error('Invalid API key');
} else if (error.status === 429) {
console.error('Rate limit exceeded - wait and retry');
} else {
console.error('Unexpected error:', error.message);
}
throw error;
}
}
// =============================================================================
// BATCH GENERATION (Sequential)
// =============================================================================
async function batchGeneration() {
const prompts = [
'A red apple on a wooden table',
'A blue butterfly on a flower',
'A green forest path in autumn',
];
const results = [];
for (const prompt of prompts) {
console.log(`Generating: ${prompt}`);
const image = await openai.images.generate({
model: 'dall-e-3',
prompt,
size: '1024x1024',
quality: 'standard',
});
results.push({
prompt,
url: image.data[0].url,
revised_prompt: image.data[0].revised_prompt,
});
// Wait 1 second between requests to avoid rate limits
await new Promise(resolve => setTimeout(resolve, 1000));
}
console.log(`Generated ${results.length} images`);
return results;
}
// =============================================================================
// MAIN EXECUTION
// =============================================================================
async function main() {
console.log('=== OpenAI DALL-E 3 Image Generation Examples ===\n');
// Example 1: Basic generation
console.log('1. Basic Image Generation:');
await basicGeneration();
console.log();
// Example 2: Quality comparison
console.log('2. Quality Comparison (Standard vs HD):');
await qualityComparison();
console.log();
// Example 3: Style comparison
console.log('3. Style Comparison (Vivid vs Natural):');
await styleComparison();
console.log();
// Example 4: Different sizes
console.log('4. Different Sizes:');
await differentSizes();
console.log();
// Example 5: Base64 output
console.log('5. Base64 Output and Save:');
await base64Output();
console.log();
// Example 6: Generate and save
console.log('6. Generate and Save:');
await generateAndSave();
console.log();
// Example 7: Detailed prompts
console.log('7. Detailed Prompt Examples:');
await detailedPrompts();
console.log();
}
// Run if executed directly
if (require.main === module) {
main().catch(console.error);
}
export {
basicGeneration,
qualityComparison,
styleComparison,
differentSizes,
base64Output,
generateAndSave,
detailedPrompts,
batchGeneration,
withErrorHandling,
};

399
templates/moderation.ts Normal file
View File

@@ -0,0 +1,399 @@
/**
* OpenAI Moderation API - Content Safety Examples
*
* This template demonstrates:
* - Basic content moderation
* - All 11 safety categories
* - Category scoring and thresholds
* - Batch moderation
* - Production patterns for UGC
*/
import OpenAI from 'openai';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
// =============================================================================
// BASIC MODERATION
// =============================================================================
async function basicModeration() {
const moderation = await openai.moderations.create({
model: 'omni-moderation-latest',
input: 'I want to hurt someone.',
});
const result = moderation.results[0];
console.log('Flagged:', result.flagged);
console.log('Categories flagged:');
Object.entries(result.categories).forEach(([category, flagged]) => {
if (flagged) {
console.log(` - ${category}: ${result.category_scores[category].toFixed(4)}`);
}
});
return result;
}
// =============================================================================
// ALL SAFETY CATEGORIES
// =============================================================================
async function allCategories() {
const examples = {
sexual: 'Explicit sexual content example',
hate: 'Hateful speech based on identity',
harassment: 'Bullying and intimidation example',
'self-harm': 'Content promoting self-harm',
'sexual/minors': 'Any sexualization of minors',
'hate/threatening': 'Violent threats based on identity',
'violence/graphic': 'Graphic violence description',
'self-harm/intent': 'Active suicidal ideation',
'self-harm/instructions': 'How to self-harm instructions',
'harassment/threatening': 'Violent threat toward individual',
violence: 'General violent content',
};
console.log('Safety Categories:\n');
for (const [category, description] of Object.entries(examples)) {
console.log(`${category}:`);
console.log(` Description: ${description}`);
}
console.log('\nNote: Use actual content for real moderation, not descriptions');
}
// =============================================================================
// CATEGORY SCORES AND THRESHOLDS
// =============================================================================
interface Thresholds {
[key: string]: number;
}
const recommendedThresholds: Thresholds = {
sexual: 0.5,
hate: 0.4,
harassment: 0.5,
'self-harm': 0.3,
'sexual/minors': 0.1, // Lower threshold for child safety
'hate/threatening': 0.3,
'violence/graphic': 0.5,
'self-harm/intent': 0.2,
'self-harm/instructions': 0.2,
'harassment/threatening': 0.3,
violence: 0.5,
};
function checkThresholds(result: any, thresholds: Thresholds): boolean {
return Object.entries(result.category_scores).some(
([category, score]) => score > (thresholds[category] || 0.5)
);
}
async function withCustomThresholds(text: string) {
const moderation = await openai.moderations.create({
model: 'omni-moderation-latest',
input: text,
});
const result = moderation.results[0];
const isFlagged = checkThresholds(result, recommendedThresholds);
console.log('Content:', text);
console.log('API flagged:', result.flagged);
console.log('Custom thresholds flagged:', isFlagged);
if (isFlagged) {
console.log('Flagged categories:');
Object.entries(result.category_scores).forEach(([category, score]) => {
const threshold = recommendedThresholds[category] || 0.5;
if (score > threshold) {
console.log(` - ${category}: ${score.toFixed(4)} (threshold: ${threshold})`);
}
});
}
return { result, isFlagged };
}
// =============================================================================
// BATCH MODERATION
// =============================================================================
async function batchModeration() {
const texts = [
'This is a normal, safe comment',
'Potentially harmful content example',
'Another safe piece of text',
];
const moderation = await openai.moderations.create({
model: 'omni-moderation-latest',
input: texts,
});
moderation.results.forEach((result, index) => {
console.log(`\nInput ${index + 1}: "${texts[index]}"`);
console.log('Flagged:', result.flagged);
if (result.flagged) {
const flaggedCategories = Object.keys(result.categories).filter(
cat => result.categories[cat]
);
console.log('Categories:', flaggedCategories.join(', '));
}
});
return moderation.results;
}
// =============================================================================
// PRODUCTION PATTERN - UGC MODERATION
// =============================================================================
interface ModerationDecision {
allowed: boolean;
reason?: string;
severity?: 'low' | 'medium' | 'high' | 'error';
scores?: any;
}
async function moderateUserContent(userInput: string): Promise<ModerationDecision> {
try {
const moderation = await openai.moderations.create({
model: 'omni-moderation-latest',
input: userInput,
});
const result = moderation.results[0];
// Immediate block for severe categories
const severeCategories = [
'sexual/minors',
'self-harm/intent',
'hate/threatening',
'harassment/threatening',
];
for (const category of severeCategories) {
if (result.categories[category]) {
return {
allowed: false,
reason: `Content violates policy: ${category}`,
severity: 'high',
};
}
}
// High-confidence violence check
if (result.category_scores.violence > 0.8) {
return {
allowed: false,
reason: 'High-confidence violence detected',
severity: 'medium',
};
}
// Self-harm content requires human review
if (result.categories['self-harm']) {
return {
allowed: false,
reason: 'Content flagged for human review',
severity: 'medium',
};
}
// Allow content
return {
allowed: true,
scores: result.category_scores,
};
} catch (error: any) {
console.error('Moderation error:', error);
// Fail closed: block on error
return {
allowed: false,
reason: 'Moderation service unavailable',
severity: 'error',
};
}
}
// =============================================================================
// CATEGORY-SPECIFIC FILTERING
// =============================================================================
async function filterByCategory(text: string, categoriesToCheck: string[]) {
const moderation = await openai.moderations.create({
model: 'omni-moderation-latest',
input: text,
});
const result = moderation.results[0];
const violations = categoriesToCheck.filter(
category => result.categories[category]
);
if (violations.length > 0) {
console.log('Content violates:', violations.join(', '));
return false;
}
console.log('Content passed specified category checks');
return true;
}
// =============================================================================
// LOGGING AND AUDIT TRAIL
// =============================================================================
interface ModerationLog {
timestamp: string;
content: string;
flagged: boolean;
categories: string[];
scores: any;
action: 'allowed' | 'blocked' | 'review';
}
async function moderateWithLogging(content: string): Promise<ModerationLog> {
const moderation = await openai.moderations.create({
model: 'omni-moderation-latest',
input: content,
});
const result = moderation.results[0];
const flaggedCategories = Object.keys(result.categories).filter(
cat => result.categories[cat]
);
const log: ModerationLog = {
timestamp: new Date().toISOString(),
content: content.substring(0, 100), // Truncate for logging
flagged: result.flagged,
categories: flaggedCategories,
scores: result.category_scores,
action: result.flagged ? 'blocked' : 'allowed',
};
// In production: save to database or logging service
console.log('Moderation log:', JSON.stringify(log, null, 2));
return log;
}
// =============================================================================
// USER FEEDBACK PATTERN
// =============================================================================
function getUserFriendlyMessage(result: any): string {
if (!result.flagged) {
return 'Content approved';
}
const flaggedCategories = Object.keys(result.categories).filter(
cat => result.categories[cat]
);
// Don't reveal exact detection details
if (flaggedCategories.some(cat => cat.includes('harm'))) {
return 'Your content appears to contain concerning material. Please review our community guidelines.';
}
if (flaggedCategories.includes('harassment') || flaggedCategories.includes('hate')) {
return 'Your content may be disrespectful or harmful to others. Please rephrase.';
}
if (flaggedCategories.includes('violence')) {
return 'Your content contains violent themes that violate our policies.';
}
return 'Your content doesn\'t meet our community guidelines. Please revise and try again.';
}
// =============================================================================
// ERROR HANDLING
// =============================================================================
async function withErrorHandling(text: string) {
try {
const moderation = await openai.moderations.create({
model: 'omni-moderation-latest',
input: text,
});
return moderation.results[0];
} catch (error: any) {
if (error.status === 401) {
console.error('Invalid API key');
} else if (error.status === 429) {
console.error('Rate limit exceeded - implement retry logic');
} else if (error.status === 500) {
console.error('OpenAI service error - fail closed and block content');
} else {
console.error('Unexpected error:', error.message);
}
throw error;
}
}
// =============================================================================
// MAIN EXECUTION
// =============================================================================
async function main() {
console.log('=== OpenAI Moderation API Examples ===\n');
// Example 1: Basic moderation
console.log('1. Basic Moderation:');
await basicModeration();
console.log();
// Example 2: All categories
console.log('2. All Safety Categories:');
allCategories();
console.log();
// Example 3: Custom thresholds
console.log('3. Custom Thresholds:');
await withCustomThresholds('This is a test message');
console.log();
// Example 4: Batch moderation
console.log('4. Batch Moderation:');
await batchModeration();
console.log();
// Example 5: Production pattern
console.log('5. Production UGC Moderation:');
const decision = await moderateUserContent('Safe user comment');
console.log('Decision:', decision);
console.log();
}
// Run if executed directly
if (require.main === module) {
main().catch(console.error);
}
export {
basicModeration,
allCategories,
withCustomThresholds,
batchModeration,
moderateUserContent,
filterByCategory,
moderateWithLogging,
getUserFriendlyMessage,
withErrorHandling,
};

23
templates/package.json Normal file
View File

@@ -0,0 +1,23 @@
{
"name": "openai-api-examples",
"version": "1.0.0",
"description": "OpenAI API examples for Chat Completions, Embeddings, Images, Audio, and Moderation",
"type": "module",
"scripts": {
"chat-basic": "tsx templates/chat-completion-basic.ts",
"chat-nodejs": "tsx templates/chat-completion-nodejs.ts",
"stream": "tsx templates/streaming-chat.ts",
"functions": "tsx templates/function-calling.ts"
},
"dependencies": {
"openai": "^6.7.0"
},
"devDependencies": {
"@types/node": "^20.11.0",
"tsx": "^4.7.0",
"typescript": "^5.3.3"
},
"engines": {
"node": ">=18.0.0"
}
}

View File

@@ -0,0 +1,415 @@
/**
* OpenAI Rate Limit Handling - Production Patterns
*
* This template demonstrates:
* - Exponential backoff
* - Rate limit header monitoring
* - Request queuing
* - Retry logic
* - Circuit breaker pattern
* - Token bucket algorithm
*/
import OpenAI from 'openai';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
// =============================================================================
// EXPONENTIAL BACKOFF
// =============================================================================
async function exponentialBackoff<T>(
fn: () => Promise<T>,
maxRetries: number = 3,
baseDelay: number = 1000
): Promise<T> {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error: any) {
// Only retry on rate limit errors
if (error.status === 429 && i < maxRetries - 1) {
const delay = baseDelay * Math.pow(2, i); // 1s, 2s, 4s
console.log(`Rate limit hit. Retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
throw error;
}
}
throw new Error('Max retries exceeded');
}
// Usage example
async function chatWithRetry() {
return exponentialBackoff(async () => {
return await openai.chat.completions.create({
model: 'gpt-5',
messages: [{ role: 'user', content: 'Hello!' }],
});
});
}
// =============================================================================
// RATE LIMIT HEADER MONITORING
// =============================================================================
interface RateLimitInfo {
limitRequests: number;
remainingRequests: number;
resetRequests: string;
limitTokens: number;
remainingTokens: number;
resetTokens: string;
}
async function checkRateLimits(): Promise<RateLimitInfo> {
const response = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'gpt-5',
messages: [{ role: 'user', content: 'ping' }],
max_tokens: 1,
}),
});
const rateLimits: RateLimitInfo = {
limitRequests: parseInt(response.headers.get('x-ratelimit-limit-requests') || '0'),
remainingRequests: parseInt(response.headers.get('x-ratelimit-remaining-requests') || '0'),
resetRequests: response.headers.get('x-ratelimit-reset-requests') || '',
limitTokens: parseInt(response.headers.get('x-ratelimit-limit-tokens') || '0'),
remainingTokens: parseInt(response.headers.get('x-ratelimit-remaining-tokens') || '0'),
resetTokens: response.headers.get('x-ratelimit-reset-tokens') || '',
};
console.log('Rate limits:', rateLimits);
return rateLimits;
}
// =============================================================================
// REQUEST QUEUE
// =============================================================================
class RequestQueue {
private queue: Array<() => Promise<any>> = [];
private processing = false;
private requestsPerMinute: number;
private lastRequestTime: number = 0;
constructor(requestsPerMinute: number) {
this.requestsPerMinute = requestsPerMinute;
}
async enqueue<T>(fn: () => Promise<T>): Promise<T> {
return new Promise((resolve, reject) => {
this.queue.push(async () => {
try {
const result = await fn();
resolve(result);
} catch (error) {
reject(error);
}
});
this.processQueue();
});
}
private async processQueue() {
if (this.processing || this.queue.length === 0) {
return;
}
this.processing = true;
while (this.queue.length > 0) {
const now = Date.now();
const minInterval = 60000 / this.requestsPerMinute;
const timeSinceLastRequest = now - this.lastRequestTime;
if (timeSinceLastRequest < minInterval) {
await new Promise(resolve =>
setTimeout(resolve, minInterval - timeSinceLastRequest)
);
}
const fn = this.queue.shift();
if (fn) {
this.lastRequestTime = Date.now();
await fn();
}
}
this.processing = false;
}
}
// Usage example
const queue = new RequestQueue(50); // 50 requests per minute
async function queuedRequest() {
return queue.enqueue(async () => {
return await openai.chat.completions.create({
model: 'gpt-5',
messages: [{ role: 'user', content: 'Hello!' }],
});
});
}
// =============================================================================
// CIRCUIT BREAKER
// =============================================================================
class CircuitBreaker {
private failures = 0;
private successCount = 0;
private lastFailureTime = 0;
private state: 'CLOSED' | 'OPEN' | 'HALF_OPEN' = 'CLOSED';
constructor(
private failureThreshold: number = 5,
private successThreshold: number = 2,
private timeout: number = 60000 // 1 minute
) {}
async execute<T>(fn: () => Promise<T>): Promise<T> {
if (this.state === 'OPEN') {
const now = Date.now();
if (now - this.lastFailureTime < this.timeout) {
throw new Error('Circuit breaker is OPEN');
}
this.state = 'HALF_OPEN';
}
try {
const result = await fn();
if (this.state === 'HALF_OPEN') {
this.successCount++;
if (this.successCount >= this.successThreshold) {
this.state = 'CLOSED';
this.failures = 0;
this.successCount = 0;
}
}
return result;
} catch (error) {
this.failures++;
this.lastFailureTime = Date.now();
if (this.failures >= this.failureThreshold) {
this.state = 'OPEN';
console.error('Circuit breaker tripped to OPEN');
}
throw error;
}
}
getState() {
return this.state;
}
}
// Usage example
const breaker = new CircuitBreaker(5, 2, 60000);
async function protectedRequest() {
return breaker.execute(async () => {
return await openai.chat.completions.create({
model: 'gpt-5',
messages: [{ role: 'user', content: 'Hello!' }],
});
});
}
// =============================================================================
// TOKEN BUCKET ALGORITHM
// =============================================================================
class TokenBucket {
private tokens: number;
private lastRefill: number;
constructor(
private capacity: number,
private refillRate: number // tokens per second
) {
this.tokens = capacity;
this.lastRefill = Date.now();
}
private refill() {
const now = Date.now();
const elapsed = (now - this.lastRefill) / 1000;
const tokensToAdd = elapsed * this.refillRate;
this.tokens = Math.min(this.capacity, this.tokens + tokensToAdd);
this.lastRefill = now;
}
async consume(tokens: number = 1): Promise<void> {
this.refill();
if (this.tokens >= tokens) {
this.tokens -= tokens;
return;
}
// Wait until enough tokens are available
const deficit = tokens - this.tokens;
const waitTime = (deficit / this.refillRate) * 1000;
await new Promise(resolve => setTimeout(resolve, waitTime));
this.tokens = 0;
}
}
// Usage example
const bucket = new TokenBucket(10, 2); // 10 tokens, refill 2 per second
async function rateLimitedRequest() {
await bucket.consume(1);
return await openai.chat.completions.create({
model: 'gpt-5',
messages: [{ role: 'user', content: 'Hello!' }],
});
}
// =============================================================================
// COMBINED PRODUCTION PATTERN
// =============================================================================
class RateLimitedClient {
private queue: RequestQueue;
private breaker: CircuitBreaker;
private bucket: TokenBucket;
constructor() {
this.queue = new RequestQueue(50); // 50 RPM
this.breaker = new CircuitBreaker(5, 2, 60000);
this.bucket = new TokenBucket(50, 1); // 50 tokens, 1 per second
}
async chatCompletion(params: any, maxRetries: number = 3) {
return this.queue.enqueue(async () => {
return exponentialBackoff(async () => {
return this.breaker.execute(async () => {
await this.bucket.consume(1);
return await openai.chat.completions.create(params);
});
}, maxRetries);
});
}
}
// Usage
const client = new RateLimitedClient();
async function productionRequest() {
return client.chatCompletion({
model: 'gpt-5',
messages: [{ role: 'user', content: 'Hello!' }],
});
}
// =============================================================================
// MONITORING AND LOGGING
// =============================================================================
interface RequestLog {
timestamp: string;
success: boolean;
retries: number;
error?: string;
latency: number;
}
async function monitoredRequest(): Promise<RequestLog> {
const startTime = Date.now();
let retries = 0;
try {
const result = await exponentialBackoff(async () => {
retries++;
return await openai.chat.completions.create({
model: 'gpt-5',
messages: [{ role: 'user', content: 'Hello!' }],
});
});
const latency = Date.now() - startTime;
return {
timestamp: new Date().toISOString(),
success: true,
retries: retries - 1,
latency,
};
} catch (error: any) {
const latency = Date.now() - startTime;
return {
timestamp: new Date().toISOString(),
success: false,
retries: retries - 1,
error: error.message,
latency,
};
}
}
// =============================================================================
// MAIN EXECUTION
// =============================================================================
async function main() {
console.log('=== OpenAI Rate Limit Handling Examples ===\n');
// Example 1: Exponential backoff
console.log('1. Exponential Backoff:');
await chatWithRetry();
console.log('Request successful with retry logic');
console.log();
// Example 2: Check rate limits
console.log('2. Check Rate Limits:');
await checkRateLimits();
console.log();
// Example 3: Production pattern
console.log('3. Production Rate-Limited Client:');
await productionRequest();
console.log('Request processed through production pipeline');
console.log();
}
// Run if executed directly
if (require.main === module) {
main().catch(console.error);
}
export {
exponentialBackoff,
checkRateLimits,
RequestQueue,
CircuitBreaker,
TokenBucket,
RateLimitedClient,
monitoredRequest,
};

View File

@@ -0,0 +1,38 @@
// Streaming Chat Completion (Node.js SDK)
// Real-time token-by-token delivery for better UX
import OpenAI from 'openai';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
async function streamingChat() {
console.log('Streaming response:\n');
const stream = await openai.chat.completions.create({
model: 'gpt-5',
messages: [
{
role: 'system',
content: 'You are a creative writer.'
},
{
role: 'user',
content: 'Write a short poem about coding'
}
],
stream: true,
max_tokens: 200,
});
// Process stream chunks
for await (const chunk of stream) {
const content = chunk.choices[0]?.delta?.content || '';
process.stdout.write(content);
}
console.log('\n\nStream complete!');
}
streamingChat();

View File

@@ -0,0 +1,86 @@
// Streaming Chat Completion (Fetch API - Cloudflare Workers)
// Server-Sent Events (SSE) parsing for edge runtimes
interface Env {
OPENAI_API_KEY: string;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
if (request.method !== 'POST') {
return new Response('Method not allowed', { status: 405 });
}
const { message } = await request.json() as { message: string };
// Call OpenAI with streaming
const response = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${env.OPENAI_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'gpt-5',
messages: [
{ role: 'user', content: message }
],
stream: true,
}),
});
// Create a transformed stream for the client
const { readable, writable } = new TransformStream();
const writer = writable.getWriter();
const encoder = new TextEncoder();
// Process SSE stream
(async () => {
const reader = response.body?.getReader();
const decoder = new TextDecoder();
try {
while (true) {
const { done, value } = await reader!.read();
if (done) break;
const chunk = decoder.decode(value);
const lines = chunk.split('\n').filter(line => line.trim() !== '');
for (const line of lines) {
if (line.startsWith('data: ')) {
const data = line.slice(6);
if (data === '[DONE]') {
await writer.write(encoder.encode('data: [DONE]\n\n'));
break;
}
try {
const json = JSON.parse(data);
const content = json.choices[0]?.delta?.content || '';
if (content) {
// Forward to client
await writer.write(encoder.encode(`data: ${JSON.stringify({ content })}\n\n`));
}
} catch (e) {
// Skip invalid JSON
}
}
}
}
} finally {
await writer.close();
}
})();
return new Response(readable, {
headers: {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
},
});
},
};

View File

@@ -0,0 +1,440 @@
/**
* OpenAI Structured Outputs - JSON Schema Examples
*
* This template demonstrates:
* - JSON schema with strict mode
* - Complex nested schemas
* - Type-safe responses
* - Validation patterns
* - Common use cases (extraction, classification, formatting)
*/
import OpenAI from 'openai';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
// =============================================================================
// BASIC STRUCTURED OUTPUT
// =============================================================================
async function basicStructuredOutput() {
const completion = await openai.chat.completions.create({
model: 'gpt-4o', // Best for structured outputs
messages: [
{ role: 'user', content: 'Generate a person profile' }
],
response_format: {
type: 'json_schema',
json_schema: {
name: 'person_profile',
strict: true,
schema: {
type: 'object',
properties: {
name: { type: 'string' },
age: { type: 'number' },
email: { type: 'string' },
},
required: ['name', 'age', 'email'],
additionalProperties: false,
},
},
},
});
const person = JSON.parse(completion.choices[0].message.content!);
console.log('Person:', person);
return person;
}
// =============================================================================
// COMPLEX NESTED SCHEMA
// =============================================================================
async function complexSchema() {
const completion = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [
{ role: 'user', content: 'Generate a company organizational structure' }
],
response_format: {
type: 'json_schema',
json_schema: {
name: 'org_structure',
strict: true,
schema: {
type: 'object',
properties: {
company: { type: 'string' },
founded: { type: 'number' },
departments: {
type: 'array',
items: {
type: 'object',
properties: {
name: { type: 'string' },
head: { type: 'string' },
employees: {
type: 'array',
items: {
type: 'object',
properties: {
name: { type: 'string' },
role: { type: 'string' },
years: { type: 'number' },
},
required: ['name', 'role', 'years'],
additionalProperties: false,
},
},
},
required: ['name', 'head', 'employees'],
additionalProperties: false,
},
},
},
required: ['company', 'founded', 'departments'],
additionalProperties: false,
},
},
},
});
const org = JSON.parse(completion.choices[0].message.content!);
console.log('Organization:', JSON.stringify(org, null, 2));
return org;
}
// =============================================================================
// DATA EXTRACTION
// =============================================================================
async function extractData() {
const text = `
John Doe is a 35-year-old software engineer living in San Francisco.
He works at TechCorp and has been there for 5 years.
His email is john.doe@example.com and his phone is (555) 123-4567.
`;
const completion = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [
{
role: 'system',
content: 'Extract structured information from the provided text.',
},
{
role: 'user',
content: text,
},
],
response_format: {
type: 'json_schema',
json_schema: {
name: 'extracted_info',
strict: true,
schema: {
type: 'object',
properties: {
name: { type: 'string' },
age: { type: 'number' },
occupation: { type: 'string' },
location: { type: 'string' },
company: { type: 'string' },
tenure_years: { type: 'number' },
contact: {
type: 'object',
properties: {
email: { type: 'string' },
phone: { type: 'string' },
},
required: ['email', 'phone'],
additionalProperties: false,
},
},
required: ['name', 'age', 'occupation', 'location', 'company', 'tenure_years', 'contact'],
additionalProperties: false,
},
},
},
});
const extracted = JSON.parse(completion.choices[0].message.content!);
console.log('Extracted:', JSON.stringify(extracted, null, 2));
return extracted;
}
// =============================================================================
// CLASSIFICATION
// =============================================================================
async function classifyText() {
const text = 'This product is absolutely terrible. It broke after one day of use. Very disappointed!';
const completion = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [
{
role: 'system',
content: 'Classify the sentiment and extract key information from product reviews.',
},
{
role: 'user',
content: text,
},
],
response_format: {
type: 'json_schema',
json_schema: {
name: 'review_classification',
strict: true,
schema: {
type: 'object',
properties: {
sentiment: {
type: 'string',
enum: ['positive', 'negative', 'neutral'],
},
confidence: { type: 'number' },
category: {
type: 'string',
enum: ['product_quality', 'customer_service', 'shipping', 'pricing', 'other'],
},
issues: {
type: 'array',
items: { type: 'string' },
},
rating_estimate: { type: 'number' },
},
required: ['sentiment', 'confidence', 'category', 'issues', 'rating_estimate'],
additionalProperties: false,
},
},
},
});
const classification = JSON.parse(completion.choices[0].message.content!);
console.log('Classification:', JSON.stringify(classification, null, 2));
return classification;
}
// =============================================================================
// SIMPLE JSON MODE (Without Strict Schema)
// =============================================================================
async function simpleJsonMode() {
const completion = await openai.chat.completions.create({
model: 'gpt-5',
messages: [
{ role: 'user', content: 'List 3 programming languages and their use cases as JSON' }
],
response_format: { type: 'json_object' },
});
const data = JSON.parse(completion.choices[0].message.content!);
console.log('JSON output:', data);
return data;
}
// =============================================================================
// ENUM VALUES
// =============================================================================
async function withEnums() {
const completion = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [
{ role: 'user', content: 'Categorize this as a bug report: The app crashes on startup' }
],
response_format: {
type: 'json_schema',
json_schema: {
name: 'issue_categorization',
strict: true,
schema: {
type: 'object',
properties: {
type: {
type: 'string',
enum: ['bug', 'feature_request', 'question', 'documentation'],
},
severity: {
type: 'string',
enum: ['critical', 'high', 'medium', 'low'],
},
component: {
type: 'string',
enum: ['frontend', 'backend', 'database', 'infrastructure', 'unknown'],
},
},
required: ['type', 'severity', 'component'],
additionalProperties: false,
},
},
},
});
const categorization = JSON.parse(completion.choices[0].message.content!);
console.log('Categorization:', categorization);
return categorization;
}
// =============================================================================
// VALIDATION EXAMPLE
// =============================================================================
function validateSchema<T>(data: any, expectedFields: string[]): T {
for (const field of expectedFields) {
if (!(field in data)) {
throw new Error(`Missing required field: ${field}`);
}
}
return data as T;
}
async function withValidation() {
const completion = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [
{ role: 'user', content: 'Generate a user profile with name and email' }
],
response_format: {
type: 'json_schema',
json_schema: {
name: 'user_profile',
strict: true,
schema: {
type: 'object',
properties: {
name: { type: 'string' },
email: { type: 'string' },
},
required: ['name', 'email'],
additionalProperties: false,
},
},
},
});
const raw = JSON.parse(completion.choices[0].message.content!);
// Validate before using
interface UserProfile {
name: string;
email: string;
}
const validated = validateSchema<UserProfile>(raw, ['name', 'email']);
console.log('Validated user:', validated);
return validated;
}
// =============================================================================
// BATCH EXTRACTION
// =============================================================================
async function batchExtraction(texts: string[]) {
const results = [];
for (const text of texts) {
const completion = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [
{ role: 'system', content: 'Extract key information as structured data' },
{ role: 'user', content: text },
],
response_format: {
type: 'json_schema',
json_schema: {
name: 'extracted_data',
strict: true,
schema: {
type: 'object',
properties: {
summary: { type: 'string' },
key_points: {
type: 'array',
items: { type: 'string' },
},
},
required: ['summary', 'key_points'],
additionalProperties: false,
},
},
},
});
const extracted = JSON.parse(completion.choices[0].message.content!);
results.push({ text, extracted });
// Rate limit protection
await new Promise(resolve => setTimeout(resolve, 1000));
}
console.log(`Extracted ${results.length} items`);
return results;
}
// =============================================================================
// MAIN EXECUTION
// =============================================================================
async function main() {
console.log('=== OpenAI Structured Outputs Examples ===\n');
// Example 1: Basic
console.log('1. Basic Structured Output:');
await basicStructuredOutput();
console.log();
// Example 2: Complex schema
console.log('2. Complex Nested Schema:');
await complexSchema();
console.log();
// Example 3: Data extraction
console.log('3. Data Extraction:');
await extractData();
console.log();
// Example 4: Classification
console.log('4. Text Classification:');
await classifyText();
console.log();
// Example 5: Simple JSON mode
console.log('5. Simple JSON Mode:');
await simpleJsonMode();
console.log();
// Example 6: Enums
console.log('6. Enum Values:');
await withEnums();
console.log();
}
// Run if executed directly
if (require.main === module) {
main().catch(console.error);
}
export {
basicStructuredOutput,
complexSchema,
extractData,
classifyText,
simpleJsonMode,
withEnums,
withValidation,
batchExtraction,
};

372
templates/text-to-speech.ts Normal file
View File

@@ -0,0 +1,372 @@
/**
* OpenAI Audio API - Text-to-Speech Examples
*
* This template demonstrates:
* - Basic TTS with all 11 voices
* - Different models (tts-1, tts-1-hd, gpt-4o-mini-tts)
* - Voice instructions (gpt-4o-mini-tts only)
* - Speed control
* - Different audio formats
* - Streaming TTS
*/
import OpenAI from 'openai';
import fs from 'fs';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
// =============================================================================
// BASIC TTS
// =============================================================================
async function basicTTS() {
const mp3 = await openai.audio.speech.create({
model: 'tts-1',
voice: 'alloy',
input: 'The quick brown fox jumped over the lazy dog.',
});
const buffer = Buffer.from(await mp3.arrayBuffer());
fs.writeFileSync('speech.mp3', buffer);
console.log('Speech saved to: speech.mp3');
}
// =============================================================================
// ALL 11 VOICES
// =============================================================================
async function allVoices() {
const voices = [
'alloy', // Neutral, balanced
'ash', // Clear, professional
'ballad', // Warm, storytelling
'coral', // Soft, friendly
'echo', // Calm, measured
'fable', // Expressive, narrative
'onyx', // Deep, authoritative
'nova', // Bright, energetic
'sage', // Wise, thoughtful
'shimmer', // Gentle, soothing
'verse', // Poetic, rhythmic
] as const;
const text = 'Hello, this is a voice sample.';
for (const voice of voices) {
console.log(`Generating ${voice} voice...`);
const mp3 = await openai.audio.speech.create({
model: 'tts-1',
voice,
input: text,
});
const buffer = Buffer.from(await mp3.arrayBuffer());
fs.writeFileSync(`speech-${voice}.mp3`, buffer);
// Wait 500ms between requests
await new Promise(resolve => setTimeout(resolve, 500));
}
console.log('All voice samples generated!');
}
// =============================================================================
// MODEL COMPARISON
// =============================================================================
async function modelComparison() {
const text = 'This is a test of different TTS models.';
// tts-1 (standard quality, fastest)
console.log('Generating with tts-1...');
const tts1 = await openai.audio.speech.create({
model: 'tts-1',
voice: 'nova',
input: text,
});
const buffer1 = Buffer.from(await tts1.arrayBuffer());
fs.writeFileSync('tts-1-output.mp3', buffer1);
// tts-1-hd (high quality)
console.log('Generating with tts-1-hd...');
const tts1Hd = await openai.audio.speech.create({
model: 'tts-1-hd',
voice: 'nova',
input: text,
});
const buffer2 = Buffer.from(await tts1Hd.arrayBuffer());
fs.writeFileSync('tts-1-hd-output.mp3', buffer2);
console.log('Model comparison complete!');
console.log('tts-1 file size:', buffer1.length, 'bytes');
console.log('tts-1-hd file size:', buffer2.length, 'bytes');
}
// =============================================================================
// VOICE INSTRUCTIONS (gpt-4o-mini-tts)
// =============================================================================
async function voiceInstructions() {
// Example 1: Calm and professional
const professional = await openai.audio.speech.create({
model: 'gpt-4o-mini-tts',
voice: 'nova',
input: 'Welcome to our customer support line. How can I help you today?',
instructions: 'Speak in a calm, professional, and friendly tone suitable for customer service.',
});
const buffer1 = Buffer.from(await professional.arrayBuffer());
fs.writeFileSync('professional-tone.mp3', buffer1);
// Example 2: Energetic and enthusiastic
const energetic = await openai.audio.speech.create({
model: 'gpt-4o-mini-tts',
voice: 'nova',
input: 'Get ready for the biggest sale of the year! Don\'t miss out!',
instructions: 'Use an enthusiastic, energetic tone perfect for marketing and advertisements.',
});
const buffer2 = Buffer.from(await energetic.arrayBuffer());
fs.writeFileSync('energetic-tone.mp3', buffer2);
// Example 3: Calm and soothing
const soothing = await openai.audio.speech.create({
model: 'gpt-4o-mini-tts',
voice: 'shimmer',
input: 'Take a deep breath. Relax your shoulders. Let all tension fade away.',
instructions: 'Adopt a calm, soothing voice suitable for meditation and relaxation guidance.',
});
const buffer3 = Buffer.from(await soothing.arrayBuffer());
fs.writeFileSync('soothing-tone.mp3', buffer3);
console.log('Voice instruction examples generated!');
}
// =============================================================================
// SPEED CONTROL
// =============================================================================
async function speedControl() {
const text = 'This sentence will be spoken at different speeds.';
const speeds = [0.5, 0.75, 1.0, 1.25, 1.5, 2.0];
for (const speed of speeds) {
console.log(`Generating at ${speed}x speed...`);
const mp3 = await openai.audio.speech.create({
model: 'tts-1',
voice: 'alloy',
input: text,
speed,
});
const buffer = Buffer.from(await mp3.arrayBuffer());
fs.writeFileSync(`speech-${speed}x.mp3`, buffer);
await new Promise(resolve => setTimeout(resolve, 500));
}
console.log('Speed variations generated!');
}
// =============================================================================
// DIFFERENT AUDIO FORMATS
// =============================================================================
async function differentFormats() {
const text = 'Testing different audio formats.';
const formats = ['mp3', 'opus', 'aac', 'flac', 'wav', 'pcm'] as const;
for (const format of formats) {
console.log(`Generating ${format} format...`);
const audio = await openai.audio.speech.create({
model: 'tts-1',
voice: 'alloy',
input: text,
response_format: format,
});
const buffer = Buffer.from(await audio.arrayBuffer());
const extension = format === 'pcm' ? 'raw' : format;
fs.writeFileSync(`speech.${extension}`, buffer);
console.log(` ${format}: ${buffer.length} bytes`);
await new Promise(resolve => setTimeout(resolve, 500));
}
console.log('All format examples generated!');
}
// =============================================================================
// LONG TEXT HANDLING
// =============================================================================
async function longText() {
const longText = `
This is a longer piece of text that demonstrates how TTS handles extended content.
The model can process up to 4096 characters in a single request.
You can use this for narrating articles, generating audiobooks, or creating voice-overs.
The speech will maintain natural pacing and intonation throughout.
`.trim();
const mp3 = await openai.audio.speech.create({
model: 'tts-1-hd',
voice: 'fable', // Good for narration
input: longText,
});
const buffer = Buffer.from(await mp3.arrayBuffer());
fs.writeFileSync('long-narration.mp3', buffer);
console.log('Long narration generated!');
console.log('Text length:', longText.length, 'characters');
console.log('Audio size:', buffer.length, 'bytes');
}
// =============================================================================
// STREAMING TTS (Server-Sent Events)
// =============================================================================
async function streamingTTS() {
const response = await fetch('https://api.openai.com/v1/audio/speech', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'gpt-4o-mini-tts',
voice: 'nova',
input: 'This is a streaming audio example. The audio will be generated and delivered in chunks.',
stream_format: 'sse', // Server-Sent Events
}),
});
console.log('Streaming TTS...');
const reader = response.body?.getReader();
const chunks: Uint8Array[] = [];
while (true) {
const { done, value } = await reader!.read();
if (done) break;
chunks.push(value);
console.log('Received chunk:', value.length, 'bytes');
}
// Combine chunks
const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
const combined = new Uint8Array(totalLength);
let offset = 0;
for (const chunk of chunks) {
combined.set(chunk, offset);
offset += chunk.length;
}
fs.writeFileSync('streaming-output.mp3', Buffer.from(combined));
console.log('Streaming TTS saved to: streaming-output.mp3');
}
// =============================================================================
// ERROR HANDLING
// =============================================================================
async function withErrorHandling() {
try {
const mp3 = await openai.audio.speech.create({
model: 'tts-1',
voice: 'alloy',
input: 'Hello world',
});
const buffer = Buffer.from(await mp3.arrayBuffer());
fs.writeFileSync('output.mp3', buffer);
return 'output.mp3';
} catch (error: any) {
if (error.message.includes('input too long')) {
console.error('Text exceeds 4096 character limit');
} else if (error.message.includes('invalid voice')) {
console.error('Voice not recognized - use one of the 11 supported voices');
} else if (error.status === 429) {
console.error('Rate limit exceeded - wait and retry');
} else {
console.error('TTS error:', error.message);
}
throw error;
}
}
// =============================================================================
// MAIN EXECUTION
// =============================================================================
async function main() {
console.log('=== OpenAI Text-to-Speech Examples ===\n');
// Example 1: Basic TTS
console.log('1. Basic TTS:');
await basicTTS();
console.log();
// Example 2: All voices (uncomment to generate all)
// console.log('2. All 11 Voices:');
// await allVoices();
// console.log();
// Example 3: Model comparison
console.log('3. Model Comparison:');
await modelComparison();
console.log();
// Example 4: Voice instructions
console.log('4. Voice Instructions (gpt-4o-mini-tts):');
await voiceInstructions();
console.log();
// Example 5: Speed control
console.log('5. Speed Control:');
await speedControl();
console.log();
// Example 6: Different formats
console.log('6. Different Audio Formats:');
await differentFormats();
console.log();
// Example 7: Long text
console.log('7. Long Text Narration:');
await longText();
console.log();
}
// Run if executed directly
if (require.main === module) {
main().catch(console.error);
}
export {
basicTTS,
allVoices,
modelComparison,
voiceInstructions,
speedControl,
differentFormats,
longText,
streamingTTS,
withErrorHandling,
};

443
templates/vision-gpt4o.ts Normal file
View File

@@ -0,0 +1,443 @@
/**
* OpenAI Vision API - GPT-4o Image Understanding
*
* This template demonstrates:
* - Image via URL
* - Image via base64
* - Multiple images in one request
* - Detailed image analysis
* - OCR / text extraction
* - Object detection
*/
import OpenAI from 'openai';
import fs from 'fs';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
// =============================================================================
// IMAGE VIA URL
// =============================================================================
async function imageViaUrl() {
const completion = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [
{
role: 'user',
content: [
{ type: 'text', text: 'What is in this image?' },
{
type: 'image_url',
image_url: {
url: 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg',
},
},
],
},
],
});
console.log('Image description:', completion.choices[0].message.content);
return completion.choices[0].message.content;
}
// =============================================================================
// IMAGE VIA BASE64
// =============================================================================
async function imageViaBase64() {
// Read image file
const imageBuffer = fs.readFileSync('./image.jpg');
const base64Image = imageBuffer.toString('base64');
const completion = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [
{
role: 'user',
content: [
{ type: 'text', text: 'Describe this image in detail' },
{
type: 'image_url',
image_url: {
url: `data:image/jpeg;base64,${base64Image}`,
},
},
],
},
],
});
console.log('Description:', completion.choices[0].message.content);
return completion.choices[0].message.content;
}
// =============================================================================
// MULTIPLE IMAGES
// =============================================================================
async function multipleImages() {
const completion = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [
{
role: 'user',
content: [
{ type: 'text', text: 'Compare these two images. What are the differences?' },
{
type: 'image_url',
image_url: {
url: 'https://example.com/image1.jpg',
},
},
{
type: 'image_url',
image_url: {
url: 'https://example.com/image2.jpg',
},
},
],
},
],
});
console.log('Comparison:', completion.choices[0].message.content);
return completion.choices[0].message.content;
}
// =============================================================================
// DETAILED IMAGE ANALYSIS
// =============================================================================
async function detailedAnalysis(imageUrl: string) {
const completion = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [
{
role: 'system',
content: 'You are an expert image analyst. Provide detailed, structured analysis of images.',
},
{
role: 'user',
content: [
{
type: 'text',
text: `Analyze this image in detail. Include:
1. Main subject/objects
2. Colors and composition
3. Lighting and mood
4. Background elements
5. Any text visible
6. Estimated context/setting`,
},
{
type: 'image_url',
image_url: { url: imageUrl },
},
],
},
],
});
console.log('Detailed analysis:', completion.choices[0].message.content);
return completion.choices[0].message.content;
}
// =============================================================================
// OCR / TEXT EXTRACTION
// =============================================================================
async function extractText(imageUrl: string) {
const completion = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [
{
role: 'user',
content: [
{ type: 'text', text: 'Extract all text visible in this image' },
{
type: 'image_url',
image_url: { url: imageUrl },
},
],
},
],
});
console.log('Extracted text:', completion.choices[0].message.content);
return completion.choices[0].message.content;
}
// =============================================================================
// OBJECT DETECTION
// =============================================================================
async function detectObjects(imageUrl: string) {
const completion = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [
{
role: 'user',
content: [
{ type: 'text', text: 'List all objects visible in this image with their approximate locations' },
{
type: 'image_url',
image_url: { url: imageUrl },
},
],
},
],
});
console.log('Objects detected:', completion.choices[0].message.content);
return completion.choices[0].message.content;
}
// =============================================================================
// IMAGE CLASSIFICATION
// =============================================================================
async function classifyImage(imageUrl: string) {
const completion = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [
{
role: 'user',
content: [
{
type: 'text',
text: 'Classify this image into categories: nature, urban, people, objects, abstract, other',
},
{
type: 'image_url',
image_url: { url: imageUrl },
},
],
},
],
});
console.log('Classification:', completion.choices[0].message.content);
return completion.choices[0].message.content;
}
// =============================================================================
// STRUCTURED OUTPUT WITH VISION
// =============================================================================
async function structuredVisionOutput(imageUrl: string) {
const completion = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [
{
role: 'user',
content: [
{ type: 'text', text: 'Analyze this image and return structured data' },
{
type: 'image_url',
image_url: { url: imageUrl },
},
],
},
],
response_format: {
type: 'json_schema',
json_schema: {
name: 'image_analysis',
strict: true,
schema: {
type: 'object',
properties: {
main_subject: { type: 'string' },
objects: {
type: 'array',
items: { type: 'string' },
},
colors: {
type: 'array',
items: { type: 'string' },
},
mood: { type: 'string' },
setting: { type: 'string' },
has_text: { type: 'boolean' },
},
required: ['main_subject', 'objects', 'colors', 'mood', 'setting', 'has_text'],
additionalProperties: false,
},
},
},
});
const analysis = JSON.parse(completion.choices[0].message.content!);
console.log('Structured analysis:', JSON.stringify(analysis, null, 2));
return analysis;
}
// =============================================================================
// MULTI-TURN CONVERSATION WITH VISION
// =============================================================================
async function conversationWithVision() {
const messages: any[] = [
{
role: 'user',
content: [
{ type: 'text', text: 'What is in this image?' },
{
type: 'image_url',
image_url: {
url: 'https://example.com/image.jpg',
},
},
],
},
];
// First turn
const response1 = await openai.chat.completions.create({
model: 'gpt-4o',
messages,
});
console.log('Turn 1:', response1.choices[0].message.content);
messages.push(response1.choices[0].message);
// Follow-up question
messages.push({
role: 'user',
content: 'Can you describe the colors in more detail?',
});
const response2 = await openai.chat.completions.create({
model: 'gpt-4o',
messages,
});
console.log('Turn 2:', response2.choices[0].message.content);
return messages;
}
// =============================================================================
// BATCH IMAGE ANALYSIS
// =============================================================================
async function batchAnalysis(imageUrls: string[]) {
const results = [];
for (const url of imageUrls) {
console.log(`Analyzing: ${url}`);
const completion = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [
{
role: 'user',
content: [
{ type: 'text', text: 'Briefly describe this image' },
{ type: 'image_url', image_url: { url } },
],
},
],
});
results.push({
url,
description: completion.choices[0].message.content,
});
// Rate limit protection
await new Promise(resolve => setTimeout(resolve, 1000));
}
console.log(`Analyzed ${results.length} images`);
return results;
}
// =============================================================================
// ERROR HANDLING
// =============================================================================
async function withErrorHandling(imageUrl: string) {
try {
const completion = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [
{
role: 'user',
content: [
{ type: 'text', text: 'What is in this image?' },
{ type: 'image_url', image_url: { url: imageUrl } },
],
},
],
});
return completion.choices[0].message.content;
} catch (error: any) {
if (error.message.includes('invalid image')) {
console.error('Image URL is invalid or inaccessible');
} else if (error.message.includes('base64')) {
console.error('Base64 encoding error');
} else if (error.status === 429) {
console.error('Rate limit exceeded');
} else {
console.error('Vision API error:', error.message);
}
throw error;
}
}
// =============================================================================
// MAIN EXECUTION
// =============================================================================
async function main() {
console.log('=== OpenAI Vision (GPT-4o) Examples ===\n');
// Example 1: Image via URL
console.log('1. Image via URL:');
await imageViaUrl();
console.log();
// Example 2: Image via base64 (uncomment when you have image.jpg)
// console.log('2. Image via Base64:');
// await imageViaBase64();
// console.log();
// Example 3: Multiple images
// console.log('3. Multiple Images:');
// await multipleImages();
// console.log();
}
// Run if executed directly
if (require.main === module) {
main().catch(console.error);
}
export {
imageViaUrl,
imageViaBase64,
multipleImages,
detailedAnalysis,
extractText,
detectObjects,
classifyImage,
structuredVisionOutput,
conversationWithVision,
batchAnalysis,
withErrorHandling,
};