331 lines
10 KiB
TypeScript
331 lines
10 KiB
TypeScript
/**
|
|
* Structured Response Types Example
|
|
*
|
|
* This example demonstrates how to use custom response types to get
|
|
* structured, type-safe outputs from AI providers. The library automatically
|
|
* generates system prompts that instruct the AI on the expected output format.
|
|
*/
|
|
|
|
import {
|
|
createClaudeProvider,
|
|
createResponseType,
|
|
parseAndValidateResponseType,
|
|
AIProviderError,
|
|
AIErrorType
|
|
} from '../src/index.js';
|
|
|
|
// ============================================================================
|
|
// DEFINE CUSTOM RESPONSE TYPES
|
|
// ============================================================================
|
|
|
|
// Example 1: User Profile Type
|
|
interface UserProfile {
|
|
name: string;
|
|
age: number;
|
|
email: string;
|
|
preferences: {
|
|
theme: 'light' | 'dark';
|
|
notifications: boolean;
|
|
};
|
|
skills: string[];
|
|
}
|
|
|
|
const userProfileType = createResponseType<UserProfile>(
|
|
'A user profile with personal information, preferences, and skills',
|
|
{
|
|
name: 'John Doe',
|
|
age: 30,
|
|
email: 'john@example.com',
|
|
preferences: { theme: 'dark', notifications: true },
|
|
skills: ['TypeScript', 'React', 'Node.js']
|
|
}
|
|
);
|
|
|
|
// Example 2: Product Analysis Type
|
|
interface ProductAnalysis {
|
|
productName: string;
|
|
category: string;
|
|
priceRange: 'budget' | 'mid-range' | 'premium';
|
|
pros: string[];
|
|
cons: string[];
|
|
overallRating: number; // 1-10 scale
|
|
recommendation: 'buy' | 'consider' | 'avoid';
|
|
reasoning: string;
|
|
}
|
|
|
|
const productAnalysisType = createResponseType<ProductAnalysis>(
|
|
'A comprehensive product analysis with pros, cons, rating, and recommendation',
|
|
{
|
|
productName: 'Example Product',
|
|
category: 'Electronics',
|
|
priceRange: 'mid-range',
|
|
pros: ['Good build quality', 'Reasonable price'],
|
|
cons: ['Limited features', 'Short warranty'],
|
|
overallRating: 7,
|
|
recommendation: 'consider',
|
|
reasoning: 'Good value for money but has some limitations'
|
|
}
|
|
);
|
|
|
|
// Example 3: Code Review Type
|
|
interface CodeReview {
|
|
overallScore: number; // 1-10 scale
|
|
issues: Array<{
|
|
type: 'error' | 'warning' | 'suggestion';
|
|
line?: number;
|
|
message: string;
|
|
severity: 'low' | 'medium' | 'high';
|
|
}>;
|
|
strengths: string[];
|
|
improvements: string[];
|
|
summary: string;
|
|
}
|
|
|
|
const codeReviewType = createResponseType<CodeReview>(
|
|
'A comprehensive code review with scoring, issues, and recommendations',
|
|
{
|
|
overallScore: 8,
|
|
issues: [
|
|
{ type: 'warning', line: 15, message: 'Consider using const instead of let', severity: 'low' }
|
|
],
|
|
strengths: ['Clear variable names', 'Good error handling'],
|
|
improvements: ['Add more comments', 'Consider refactoring large functions'],
|
|
summary: 'Well-written code with minor improvements needed'
|
|
}
|
|
);
|
|
|
|
// ============================================================================
|
|
// EXAMPLE FUNCTIONS
|
|
// ============================================================================
|
|
|
|
async function demonstrateUserProfileGeneration() {
|
|
console.log('\n=== User Profile Generation Example ===');
|
|
|
|
const claude = createClaudeProvider(process.env.ANTHROPIC_API_KEY || 'your-api-key-here');
|
|
await claude.initialize();
|
|
|
|
try {
|
|
const response = await claude.complete<UserProfile>({
|
|
messages: [
|
|
{
|
|
role: 'user',
|
|
content: 'Generate a realistic user profile for a software developer who loves open source projects and prefers dark themes.'
|
|
}
|
|
],
|
|
responseType: userProfileType,
|
|
maxTokens: 500,
|
|
temperature: 0.7
|
|
});
|
|
|
|
console.log('Raw response:', response.rawContent);
|
|
|
|
const userProfile = response.content;
|
|
console.log('\nParsed User Profile:');
|
|
console.log(`Name: ${userProfile.name}`);
|
|
console.log(`Age: ${userProfile.age}`);
|
|
console.log(`Email: ${userProfile.email}`);
|
|
console.log(`Theme Preference: ${userProfile.preferences.theme}`);
|
|
console.log(`Notifications: ${userProfile.preferences.notifications}`);
|
|
console.log(`Skills: ${userProfile.skills.join(', ')}`);
|
|
|
|
} catch (error) {
|
|
if (error instanceof AIProviderError) {
|
|
console.error(`AI Provider Error (${error.type}):`, error.message);
|
|
} else {
|
|
console.error('Unexpected error:', error);
|
|
}
|
|
}
|
|
}
|
|
|
|
async function demonstrateProductAnalysis() {
|
|
console.log('\n=== Product Analysis Example ===');
|
|
|
|
const claude = createClaudeProvider(process.env.ANTHROPIC_API_KEY || 'your-api-key-here');
|
|
await claude.initialize();
|
|
|
|
try {
|
|
const response = await claude.complete<ProductAnalysis>({
|
|
messages: [
|
|
{
|
|
role: 'user',
|
|
content: 'Analyze the iPhone 15 Pro from a consumer perspective. Consider its features, price point, and market position.'
|
|
}
|
|
],
|
|
responseType: productAnalysisType,
|
|
maxTokens: 800,
|
|
temperature: 0.5
|
|
});
|
|
|
|
console.log('Raw response:', response.rawContent);
|
|
|
|
const analysis = response.content;
|
|
console.log('\nProduct Analysis:');
|
|
console.log(`Product: ${analysis.productName}`);
|
|
console.log(`Category: ${analysis.category}`);
|
|
console.log(`Price Range: ${analysis.priceRange}`);
|
|
console.log(`Overall Rating: ${analysis.overallRating}/10`);
|
|
console.log(`Recommendation: ${analysis.recommendation}`);
|
|
console.log(`Pros: ${analysis.pros.join(', ')}`);
|
|
console.log(`Cons: ${analysis.cons.join(', ')}`);
|
|
console.log(`Reasoning: ${analysis.reasoning}`);
|
|
|
|
} catch (error) {
|
|
if (error instanceof AIProviderError) {
|
|
console.error(`AI Provider Error (${error.type}):`, error.message);
|
|
} else {
|
|
console.error('Unexpected error:', error);
|
|
}
|
|
}
|
|
}
|
|
|
|
async function demonstrateCodeReview() {
|
|
console.log('\n=== Code Review Example ===');
|
|
|
|
const claude = createClaudeProvider(process.env.ANTHROPIC_API_KEY || 'your-api-key-here');
|
|
await claude.initialize();
|
|
|
|
const sampleCode = `
|
|
function calculateTotal(items) {
|
|
let total = 0;
|
|
for (let i = 0; i < items.length; i++) {
|
|
total += items[i].price;
|
|
}
|
|
return total;
|
|
}
|
|
|
|
function processPayment(amount, cardNumber) {
|
|
if (amount <= 0) {
|
|
throw new Error("Invalid amount");
|
|
}
|
|
// Process payment logic here
|
|
return { success: true, transactionId: "12345" };
|
|
}
|
|
`;
|
|
|
|
try {
|
|
const response = await claude.complete<CodeReview>({
|
|
messages: [
|
|
{
|
|
role: 'user',
|
|
content: `Please review this JavaScript code and provide a comprehensive analysis:\n\n\
|
|
`${sampleCode}
|
|
\
|
|
``` `
|
|
}
|
|
],
|
|
responseType: codeReviewType,
|
|
maxTokens: 1000,
|
|
temperature: 0.3
|
|
});
|
|
|
|
console.log('Raw response:', response.rawContent);
|
|
|
|
const review = response.content;
|
|
console.log('\nCode Review:');
|
|
console.log(`Overall Score: ${review.overallScore}/10`);
|
|
console.log(`Summary: ${review.summary}`);
|
|
console.log(`\nStrengths:`);
|
|
review.strengths.forEach(strength => console.log(` • ${strength}`));
|
|
console.log(`\nImprovements:`);
|
|
review.improvements.forEach(improvement => console.log(` • ${improvement}`));
|
|
console.log(`\nIssues:`);
|
|
review.issues.forEach(issue => {
|
|
const lineInfo = issue.line ? ` (line ${issue.line})` : '';
|
|
console.log(` • [${issue.severity.toUpperCase()}] ${issue.type}: ${issue.message}${lineInfo}`);
|
|
});
|
|
|
|
} catch (error) {
|
|
if (error instanceof AIProviderError) {
|
|
console.error(`AI Provider Error (${error.type}):`, error.message);
|
|
} else {
|
|
console.error('Unexpected error:', error);
|
|
}
|
|
}
|
|
}
|
|
|
|
async function demonstrateStreamingWithResponseType() {
|
|
console.log('\n=== Streaming with Response Type Example ===');
|
|
|
|
const claude = createClaudeProvider(process.env.ANTHROPIC_API_KEY || 'your-api-key-here');
|
|
await claude.initialize();
|
|
|
|
try {
|
|
console.log('Streaming response for product analysis...\n');
|
|
|
|
let fullResponse = '';
|
|
for await (const chunk of claude.stream({
|
|
messages: [
|
|
{
|
|
role: 'user',
|
|
content: 'Analyze the Tesla Model 3 as a consumer product.'
|
|
}
|
|
],
|
|
responseType: productAnalysisType,
|
|
maxTokens: 600,
|
|
temperature: 0.5
|
|
})) {
|
|
if (!chunk.isComplete) {
|
|
process.stdout.write(chunk.content);
|
|
fullResponse += chunk.content;
|
|
} else {
|
|
console.log('\n\nStream completed. Usage:', chunk.usage);
|
|
|
|
// Validate the complete streamed response
|
|
try {
|
|
const analysis = parseAndValidateResponseType(fullResponse, productAnalysisType);
|
|
console.log('\nStreamed response validation: SUCCESS');
|
|
console.log(`Product: ${analysis.productName}`);
|
|
} catch (e) {
|
|
console.log('\nStreamed response validation: FAILED -', (e as Error).message);
|
|
}
|
|
}
|
|
}
|
|
|
|
} catch (error) {
|
|
if (error instanceof AIProviderError) {
|
|
console.error(`AI Provider Error (${error.type}):`, error.message);
|
|
} else {
|
|
console.error('Unexpected error:', error);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// MAIN EXECUTION
|
|
// ============================================================================
|
|
|
|
async function main() {
|
|
console.log('🚀 Structured Response Types Example');
|
|
console.log('=====================================');
|
|
|
|
// Check for API key
|
|
if (!process.env.ANTHROPIC_API_KEY) {
|
|
console.error('❌ Please set ANTHROPIC_API_KEY environment variable');
|
|
console.log('You can get an API key from: https://console.anthropic.com/');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await demonstrateUserProfileGeneration();
|
|
await demonstrateProductAnalysis();
|
|
await demonstrateCodeReview();
|
|
await demonstrateStreamingWithResponseType();
|
|
|
|
console.log('\n✅ All examples completed successfully!');
|
|
console.log('\nKey Benefits of Response Types:');
|
|
console.log('• Type-safe AI responses');
|
|
console.log('• Automatic system prompt generation');
|
|
console.log('• Built-in response validation');
|
|
console.log('• Consistent output format');
|
|
console.log('• Better error handling');
|
|
|
|
} catch (error) {
|
|
console.error('❌ Example failed:', error);
|
|
}
|
|
}
|
|
|
|
// Run the example
|
|
if (import.meta.main) {
|
|
main().catch(console.error);
|
|
}
|