Special Step Types
prai provides specialized step functions beyond the basic `step()` function for common data processing patterns like filtering data, combine results, and perform other operations in AI workflows.
Available step types
mapStep
- Process arrays of data with consistent promptsfilterStep
- Filter arrays based on AI-powered criteriacombineStep
- Merge multiple data sources intelligentlyselectStep
- Choose the best option from alternativesallStep
- Check if all items meet criteriasomeStep
- Check if any items meet criteriajoinStep
- Join data with intelligent matchingseparateStep
- Split data into categorieslistStep
- Generate lists based on criteria
Map Step
Process arrays of data with consistent prompts applied to each element.
import { mapStep } from 'prai'
const products = [
{ name: 'Laptop', category: 'Electronics', price: 999 },
{ name: 'Coffee Mug', category: 'Kitchen', price: 15 },
{ name: 'Notebook', category: 'Office', price: 5 }
]
const descriptions = await mapStep(
products,
(product) => `Write a marketing description for ${product.name} in the ${product.category} category, priced at $${product.price}`,
z.object({
description: z.string(),
keyFeatures: z.array(z.string()),
targetAudience: z.string(),
marketingTags: z.array(z.string())
}),
{ model, history }
)
console.log(descriptions)
// Array of descriptions, one for each product
Map Step Options
const results = await mapStep(
data,
(item) => `Process ${item.name}`,
resultSchema,
{
model,
history,
stream: true // Optional: enable streaming
}
)
Filter Step
Filter arrays based on AI-powered criteria that would be difficult to express programmatically.
import { filterStep } from 'prai'
const articles = [
{ title: 'AI in Healthcare', content: 'Machine learning is revolutionizing...' },
{ title: 'Best Coffee Recipes', content: 'Start your morning with...' },
{ title: 'Quantum Computing Basics', content: 'Quantum mechanics meets...' },
{ title: 'Cooking with Python', content: 'A cookbook for programmers...' }
]
const techArticles = await filterStep(
articles,
(article) => `Is this ${article} about technology or programming?"`,
z.boolean(),
{ model, history }
)
console.log(techArticles)
// Only articles that the AI determined were about technology
// Expected: AI in Healthcare, Quantum Computing Basics, Cooking with Python
Complex Filtering
const candidates = [
{ name: 'Alice', experience: '5 years React, 3 years Node.js', education: 'CS Degree' },
{ name: 'Bob', experience: '2 years Python, ML research', education: 'PhD Physics' },
{ name: 'Carol', experience: '8 years backend, team lead', education: 'Bootcamp grad' }
]
const suitable = await filterStep(
candidates,
(candidate) => `Is this ${candidate} suitable for a senior full-stack role requiring leadership experience?`,
z.object({
suitable: z.boolean(),
reasoning: z.string()
}),
{ model, history }
)
Combine Step
Intelligently merge multiple data sources or combine related information.
import { combineStep } from 'prai'
const userFeedback = [
'Great product, love the design!',
'Shipping was slow but quality is good',
'Customer service needs improvement',
'Best purchase I made this year'
]
const analyticsData = {
sessions: 1000,
bounceRate: 0.3,
avgSessionTime: 120,
conversionRate: 0.05
}
const competitorData = {
pricing: { average: 49.99, range: '29.99-79.99' },
features: ['feature1', 'feature2', 'feature3'],
marketShare: 0.15
}
const report = await combineStep(
[userFeedback, analyticsData, competitorData],
'Create a comprehensive product performance report combining user feedback, analytics, and competitive analysis',
z.object({
overallSummary: z.string(),
strengths: z.array(z.string()),
weaknesses: z.array(z.string()),
recommendations: z.array(z.object({
action: z.string(),
priority: z.enum(['high', 'medium', 'low']),
reasoning: z.string()
})),
competitivePosition: z.string()
}),
{ model, history }
)
Select Step
Choose the best option from a set of alternatives based on given criteria.
import { selectStep } from 'prai'
const designOptions = [
{
name: 'Modern Minimalist',
colors: ['#000000', '#ffffff', '#f5f5f5'],
style: 'clean, minimal, lots of whitespace',
targetAudience: 'professionals, millennials'
},
{
name: 'Vibrant Creative',
colors: ['#ff6b6b', '#4ecdc4', '#45b7d1'],
style: 'colorful, energetic, playful',
targetAudience: 'creatives, young adults'
},
{
name: 'Corporate Professional',
colors: ['#2c3e50', '#3498db', '#95a5a6'],
style: 'conservative, trustworthy, formal',
targetAudience: 'enterprises, executives'
}
]
const selectedDesign = await selectStep(
designOptions,
'Select the best design for a tech startup targeting young professionals who value both innovation and professionalism',
{ model, history }
)
console.log('Selected design:', selectedDesign)
// Returns the full design object that best matches the criteria
Select with Custom Scoring
const bestCandidate = await selectStep(
candidates,
'Select the best candidate for a senior developer role, considering technical skills, leadership experience, and cultural fit',
{
model,
history,
stream: false // Disable streaming for selection
}
)
All Step
Check if all items in an array meet specific criteria.
import { allStep } from 'prai'
const documents = [
{ title: 'Privacy Policy', content: '...' },
{ title: 'Terms of Service', content: '...' },
{ title: 'User Guide', content: '...' }
]
const allCompliant = await allStep(
documents,
(doc) => `Is this document GDPR compliant? Check for privacy controls, data handling, and user rights. Document: ${doc.title}`,
z.object({
compliant: z.boolean(),
issues: z.array(z.string()).optional()
}),
{ model, history }
)
console.log('All documents compliant:', allCompliant)
// Returns true only if ALL documents are compliant
Some Step
Check if any items in an array meet specific criteria.
import { someStep } from 'prai'
const emails = [
{ subject: 'Meeting reminder', content: 'Don\'t forget about tomorrow\'s meeting' },
{ subject: 'URGENT: Action required', content: 'Your account will be suspended...' },
{ subject: 'Newsletter', content: 'Here are this week\'s updates...' }
]
const hasUrgent = await someStep(
emails,
(email) => `Is this ${email} urgent and requiring immediate action?`,
z.boolean(),
{ model, history }
)
if (hasUrgent) {
console.log('You have urgent emails requiring attention')
}
Join Step
Join or match data from different sources based on intelligent criteria.
import { joinStep } from 'prai'
const customers = [
{ id: 1, name: 'John Smith', company: 'Acme Corp' },
{ id: 2, name: 'Jane Doe', company: 'Tech Solutions' }
]
const orders = [
{ orderId: 'A123', customerInfo: 'J. Smith from Acme', amount: 500 },
{ orderId: 'B456', customerInfo: 'Jane D. - Tech Solutions Inc', amount: 750 }
]
const joined = await joinStep(
customers,
orders,
(customer, order) => `Do this ${customer} and ${order} belong to the same person?`,
z.object({
customer: z.object({
id: z.number(),
name: z.string(),
company: z.string()
}),
order: z.object({
orderId: z.string(),
customerInfo: z.string(),
amount: z.number()
}),
confidence: z.number().min(0).max(1)
}),
{ model, history }
)
Separate Step
Split data into different categories based on AI analysis.
import { separateStep } from 'prai'
const mixedContent = [
{ text: 'Great product, highly recommend!' },
{ text: 'Terrible quality, waste of money' },
{ text: 'The sky is blue today' },
{ text: 'Amazing customer service' }
]
const separated = await separateStep(
mixedContent,
(item) => `Categorize this text: ${item.text}`,
z.enum(['positive_review', 'negative_review', 'neutral_comment', 'unrelated']),
{ model, history }
)
console.log(separated)
// {
// positive_review: [{ text: 'Great product...' }, { text: 'Amazing customer...' }],
// negative_review: [{ text: 'Terrible quality...' }],
// neutral_comment: [],
// unrelated: [{ text: 'The sky is blue...' }]
// }
List Step
Generate lists based on criteria or context.
import { listStep } from 'prai'
const projectContext = {
type: 'e-commerce website',
target: 'small businesses',
timeline: '3 months',
budget: 'medium'
}
const tasks = await listStep(
`Generate a comprehensive task list for developing ${projectContext.type} targeting ${projectContext.target} with a ${projectContext.timeline} timeline and ${projectContext.budget} budget`,
z.object({
phase: z.string(),
task: z.string(),
estimatedHours: z.number(),
priority: z.enum(['high', 'medium', 'low']),
dependencies: z.array(z.string()).optional()
}),
{ model, history }
)
console.log(tasks)
// Returns array of task objects