AIアプリケーション開発の現場では、LLMからの出力を 型安全な形で受信したい したいという要求が急速に高まっています。特にECサイトのAIカスタマーサービスや企業RAGシステムでは、曖昧なテキスト返すよりも、構造化されたJSONデータとして応答を受け取りたい場面が多いです。

本記事では、HolySheep AIのAPIと、Vercel AI SDK、そしてスキーマ検証ライブラリZodを組み合わせた「構造化出力」(Structured Output)の実装方法を、実践的なコード例を交えながら丁寧に解説します。

構造化出力とは?なぜ必要か

従来のLLM API呼び出しでは、文字列形式で回答を受け取ります。しかし、実務では以下のように型安全なオブジェクトとしてデータを受け取りたいケースが多くあります:

Zodを使うことで、LLMの出力を事前に定義したスキーマに厳密に従わせ、ランタイムで型検証を行うことができます。これにより、レスポンスの形式不正导致的バグを ран━━で防止できます。

前提環境とインストール

まず、必要なパッケージをインストールします。HolySheep AIはOpenAI互換APIを提供しているため、@ai-sdk/openaiパッケージをそのまま使用できます。

npm install zod zod-to-json-schema @ai-sdk/openai ai

または yarn / pnpm

yarn add zod zod-to-json-schema @ai-sdk/openai ai

環境変数の設定は以下の通りです:

// .env.local
HOLYSHEEP_API_KEY=YOUR_HOLYSHEEP_API_KEY

HolySheep APIのベースURL

VITE_API_BASE_URL=https://api.holysheep.ai/v1

HolySheep AIを選ぶ理由として、¥1=$1という業界最安水準のレート(公式¥7.3=$1比85%節約)を筆者が実際にプロジェクトで使用して実感しており、構造化出力のような大量リクエストを发送する用途に最適なコストパフォーマンスを実現します。

Zodスキーマの定義

まずは構造化したいデータのスキーマをZodで定義します。 ECサイトのAIチャットボットを想定し、顧客問い合わせから情報を抽出する例を見てみましょう。

import { z } from 'zod';

// 感情分析结果的スキーマ
const SentimentAnalysisSchema = z.object({
  sentiment: z.enum(['positive', 'negative', 'neutral']),
  confidence: z.number().min(0).max(1),
  keyPhrases: z.array(z.string()),
  summary: z.string().max(200),
});

// 顧客問い合わせ抽出のスキーマ
const CustomerInquirySchema = z.object({
  customerName: z.string().optional(),
  orderNumber: z.string().regex(/^ORD-\d{8}$/, '形式: ORD-XXXXXXXX'),
  issueType: z.enum([
    'delivery_delay',
    'product_defect',
    'wrong_item',
    'refund_request',
    'other'
  ]),
  priority: z.enum(['low', 'medium', 'high', 'urgent']),
  extractedInfo: z.object({
    productNames: z.array(z.string()),
    quantities: z.array(z.number()),
    desiredAction: z.string(),
  }),
  autoReply: z.string().optional(),
});

// 混合スキーマ(複数の可能性がある場合)
const MultiIntentSchema = z.discriminatedUnion('type', [
  z.object({
    type: z.literal('inquiry'),
    data: CustomerInquirySchema,
  }),
  z.object({
    type: z.literal('feedback'),
    data: SentimentAnalysisSchema,
  }),
]);

AI SDK + HolySheep AIで構造化出力の実装

ここからは実際のAPI呼び出しコードです。HolySheep AIは<50msの低レイテンシを実現しており、リアルタイム性が求められるチャットボット用途에도最適です。

import { createAI } from '@ai-sdk/openai';
import { z } from 'zod';
import { CustomerInquirySchema, SentimentAnalysisSchema } from './schemas';

// HolySheep AIクライアントの初期化
const holySheep = createAI({
  baseURL: 'https://api.holysheep.ai/v1',
  apiKey: process.env.HOLYSHEEP_API_KEY,
});

// 構造化出力を使用した問い合わせ分析関数
async function analyzeCustomerInquiry(userMessage: string) {
  'use strict';
  
  const response = await holySheep.chat.completions.create({
    model: 'gpt-4o-mini', // HolySheepで 지원하는 모델
    messages: [
      {
        role: 'system',
        content: `あなたはECサイトのカスタマーサービスAIです。
        顧客からの問い合わせを分析し、構造化されたデータを返してください。
        必ず指定されたJSON形式に従ってください。`
      },
      {
        role: 'user',
        content: userMessage
      }
    ],
    // ZodスキーマからJSON Schemaを生成
    response_format: {
      type: 'json_object',
      schema: {
        // CustomerInquirySchemaから変換したスキーマ
        type: 'object',
        properties: {
          customerName: { type: 'string' },
          orderNumber: { 
            type: 'string',
            pattern: '^ORD-\\d{8}$'
          },
          issueType: { 
            type: 'string',
            enum: ['delivery_delay', 'product_defect', 'wrong_item', 'refund_request', 'other']
          },
          priority: { 
            type: 'string',
            enum: ['low', 'medium', 'high', 'urgent']
          },
          extractedInfo: {
            type: 'object',
            properties: {
              productNames: { type: 'array', items: { type: 'string' } },
              quantities: { type: 'array', items: { type: 'number' } },
              desiredAction: { type: 'string' }
            },
            required: ['productNames', 'desiredAction']
          },
          autoReply: { type: 'string' }
        },
        required: ['orderNumber', 'issueType', 'priority', 'extractedInfo']
      }
    },
    temperature: 0.1, // 構造化出力には低い температураが効果的
    max_tokens: 1024,
  });

  const content = response.choices[0]?.message?.content;
  
  if (!content) {
    throw new Error('AIからの応答が空でした');
  }

  // レスポンスをパースしてZodで検証
  const parsedData = JSON.parse(content);
  return CustomerInquirySchema.parse(parsedData);
}

// 使用例
async function main() {
  try {
    const result = await analyzeCustomerInquiry(
      '注文番号ORD-20240115で届いたT恤がMサイズじゃなくてLサイズでした。' +
      '商品名は「クラシックCotton T-Shirt」、数量1点です。' +
      'すぐに交換 부탁드립니다。'
    );
    
    console.log('解析結果:', result);
    // {
    //   orderNumber: 'ORD-20240115',
    //   issueType: 'wrong_item',
    //   priority: 'high',
    //   extractedInfo: {
    //     productNames: ['クラシックCotton T-Shirt'],
    //     quantities: [1],
    //     desiredAction: '交換'
    //   }
    // }
  } catch (error) {
    console.error('エラー:', error);
  }
}

RAGシステムでの実践例

企業向けRAG(Retrieval-Augmented Generation)システムでも、構造化出力は極めて有効です。文書検索と組み合わせ、文書から抽出した情報を明確にstructured 형태로返す例を見てみましょう。

// RAG検索結果のスキーマ
const DocumentCitationSchema = z.object({
  citations: z.array(z.object({
    documentId: z.string(),
    pageNumber: z.number().optional(),
    relevanceScore: z.number().min(0).max(1),
    excerpt: z.string().max(500),
    metadata: z.record(z.any()),
  })),
  answer: z.string(),
  confidence: z.number().min(0).max(1),
  referencedPolicies: z.array(z.string()),
});

// AI SDKのstreamObjectを使用したストリーミング対応の実装
import { generateText, streamText } from 'ai';

async function ragQueryWithStructuredOutput(
  query: string,
  retrievedDocuments: Array<{ id: string; content: string; metadata: any }>
) {
  const context = retrievedDocuments
    .map((doc, i) => [文脈 ${i + 1}]\n${doc.content})
    .join('\n\n');

  const result = await generateText({
    model: holySheep.languageModel('gpt-4o'),
    system: `あなたは企业内部の知見を検索・回答するRAGアシスタントです。
    提供された文脈のみに基づいて回答し、必ず構造化されたJSONを返してください。
    文脈に情報がない場合は、"information_not_available"と返してください。`,
    messages: [
      {
        role: 'user',
        content: 文脈:\n${context}\n\n質問: ${query}
      }
    ],
    // 構造化出力の設定
    structuredOutputSchema: zodOutputSchema(DocumentCitationSchema),
  });

  // 結果は自動的にZodスキーマで検証済み
  return result.structuredOutput as z.infer;
}

// ZodスキーマからVercel AI SDK形式に変換するヘルパー
function zodOutputSchema(schema: z.ZodType) {
  return {
    parse: async (output: string) => {
      const parsed = JSON.parse(output);
      return schema.parse(parsed);
    },
  };
}

筆者が実際に企業様のRAGシステムを構築際は、このように出典情報(citations)を明確に構造化することで、回答の信頼性をユーザーが目で確認できるようになり、システムへの信任向上에大きく貢献しました。HolySheep AIの低レイテンシ 덕분에、検索結果と組み合わせた処理でも自然な対話速度を維持できています。

HolySheep AIの料金プランと成本最適化

構造化出力を大规模に实装する場合、APIコストも重要な検討事項です。HolySheep AIの2026年价格为以下通りです:

筆者の経験則では、構造化出力用途에는gpt-4o-mini또는gemini-2.0-flashがコストパフォーマンスに優れています。複雑な推論이 필요없는抽出タスクでは、DeepSeek V3.2を選択することで大幅なコスト削減が実現できます。

またHolySheep AIはWeChat Pay / Alipayに対応しており中國の开发者们も簡単に结算でき、日本語・英語・中文マルチリンガルサポート обеспечиваетされています。

よくあるエラーと対処法

エラー1: JSONパースエラー「Unexpected token」

// ❌ 错误なコード
const result = JSON.parse(response.choices[0].message.content);

// ✅ 正しい実装:nullチェックとエラーハンドリング
const content = response.choices[0]?.message?.content;
if (!content) {
  throw new Error('AIからの応答が空です。再度お試しください。');
}

try {
  const result = JSON.parse(content);
} catch (parseError) {
  // LLMがMarkdownコードブロック付きで返してきた場合の处理
  const cleanedContent = content
    .replace(/^```json\s*/i, '')
    .replace(/^```\s*/i, '')
    .replace(/\s*```$/i, '')
    .trim();
  const result = JSON.parse(cleanedContent);
}

原因: 一部のLLMはMarkdownのコードブロック(```json)付きでJSONを返すことがあります。

エラー2: Zod検証エラー「Invalid enum value」

// ❌ Zodの厳格な検証会导致错误
const result = CustomerInquirySchema.parse(parsedData);
// ZodError: Expected 'delivery_delay' | 'product_defect' | ...

// ✅ 緩やかな検証+フォールバック处理
const result = CustomerInquirySchema.safeParse(parsedData);

if (!result.success) {
  console.error('検証エラー詳細:', result.error.flatten());
  
  // 部分的な救済を試みる
  const fallbackData = {
    ...parsedData,
    issueType: parsedData.issueType || 'other',
    priority: parsedData.priority || 'medium',
  };
  
  return CustomerInquirySchema.parse(fallbackData);
}

原因: LLMが出力する列挙値の揺れ(例:「delivery delay」と「delivery_delay」の混在)。

エラー3: ストリーミング時の構造化出力エラー

// ❌ ストリーミングではJSONが完成する前にパースしてしまう
const stream = await streamText({
  model: holySheep.languageModel('gpt-4o'),
  messages,
  structuredOutputSchema: schema,
});

for await (const delta of stream.fullStream) {
  // 途中経過を無理にパースするとエラー
  const partial = JSON.parse(delta.text); // ❌ 不完全なJSON
}

// ✅ 完全なレスポンス受信後にパース
const fullResponse = await streamText({
  model: holySheep.languageModel('gpt-4o'),
  messages,
}).then(r => r.text);

const parsed = CustomerInquirySchema.parse(JSON.parse(fullResponse));

// または streamObject を使用(SDK標準機能)
const objectStream = await streamObject({
  model: holySheep.languageModel('gpt-4o'),
  schema: CustomerInquirySchema,
  prompt: userMessage,
});

for await (const partial of objectStream.partialObjectStream) {
  console.log('途中結果:', partial);
  // UIに部分的な進捗を表示できる
}

原因: ストリーミング模式下、JSONがまだ完成していない状态下でのパース尝试。

まとめ

本記事では、TypeScript + Zod + AI SDKを使用してHolySheep AIで構造化出力を実装する方法を解説しました。 핵심 포인트は以下です:

構造化出力は今すぐ aplicaçõesПрактикаに応用できる技術です。最初はシンプルなスキーマから始めて徐々に复杂なケースに対応していくRecommendedアプローチです。

👉 HolySheep AI に登録して無料クレジットを獲得