AIアプリケーション開発の現場において、モデルが出力するデータの形式を制御することは、プロダクション環境での信頼性を左右する重要な課題です。本稿では、DeepSeek V4の構造化出力機能とFunction Callingを活用し、安定稼働するAIサービスを構築するための実践的なテクニックを解説します。
なぜ構造化出力が重要なのか
私は以前、ECサイトのAIカスタマーサポートシステムを構築していた際、大量の注文データ查询リクエスト的处理に苦しみました。ユーザーが「注文番号12345の状況を教えて」と聞いた際、LLMが返す回答の形式が毎回異なると、後続の処理ロジックが崩溃寸前でした。
DeepSeek V4では、JSON Schemaを活用した構造化出力により、出力形式を明確に制御できます。今すぐ登録して、低コストで高性能なAPIを試해보세요。HolySheep AIではDeepSeek V3.2が$0.42/MTokという破格の価格で利用可能で、レートは¥1=$1(公式¥7.3=$1比85%節約)です。
Function Callingの基本設定
Function Callingは、LLMに外部ツールや関数を呼び出す能力を与える機能です。ECサイトの注文查询システムを例に、Pythonでの実装を見ていきましょう。
import openai
import json
from typing import List, Optional
HolySheep AI API設定
client = openai.OpenAI(
api_key="YOUR_HOLYSHEEP_API_KEY",
base_url="https://api.holysheep.ai/v1"
)
関数定義(注文查询)
functions = [
{
"type": "function",
"function": {
"name": "get_order_status",
"description": "注文番号に基づいて注文状況を取得する",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "10桁の注文番号"
}
},
"required": ["order_id"]
}
}
},
{
"type": "function",
"function": {
"name": "get_shipping_info",
"description": "配送状況と追跡番号を取得する",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "注文番号"
}
},
"required": ["order_id"]
}
}
}
]
def query_order(user_message: str) -> dict:
"""ユーザーからの查询を処理し、構造化された結果を返す"""
response = client.chat.completions.create(
model="deepseek-chat",
messages=[
{"role": "system", "content": "あなたはECサイトのAIアシスタントです。注文状況を確認するにはget_order_status、配送情報を取得するにはget_shipping_infoを使用してください。"},
{"role": "user", "content": user_message}
],
tools=functions,
tool_choice="auto",
response_format={"type": "json_object"}
)
return response.choices[0].message
使用例
user_query = "注文番号A1234567890の状況を教えてください"
result = query_order(user_query)
print(f"返答タイプ: {result.finish_reason}")
print(f" содержание: {result.content}")
print(f"関数呼び出し: {result.tool_calls}")
構造化出力の活用事例:企業RAGシステム
企業内文書を対象にしたRAG(Retrieval-Augmented Generation)システムを構築する際、検索結果の返答形式を一貫させることは極めて重要です。以下の例では、文書検索 결과를構造化されたフォーマットで返す実装を示します。
import openai
from pydantic import BaseModel, Field
from typing import List, Optional
from datetime import datetime
返答スキーマ定義
class DocumentAnswer(BaseModel):
"""文書検索の構造化返答"""
answer_summary: str = Field(description="質問への簡潔な回答(200文字以内)")
source_documents: List[dict] = Field(description="参照元の文書リスト")
confidence_score: float = Field(ge=0.0, le=1.0, description="回答の信頼度")
cited_pages: List[int] = Field(description="参照頁番号リスト")
follow_up_suggestions: Optional[List[str]] = Field(default=None, description="フォローアップ質問の提案")
class DocumentQuerySystem:
def __init__(self):
self.client = openai.OpenAI(
api_key="YOUR_HOLYSHEEP_API_KEY",
base_url="https://api.holysheep.ai/v1"
)
def search_and_answer(self, query: str, retrieved_docs: List[dict]) -> DocumentAnswer:
"""文書検索結果から構造化された回答を生成"""
# 文書内容をコンテキストに整形
context = "\n\n".join([
f"[文書{i+1}] ページ{p.get('page', 'N/A')}: {p.get('content', '')}"
for i, p in enumerate(retrieved_docs)
])
response = self.client.chat.completions.create(
model="deepseek-chat",
messages=[
{
"role": "system",
"content": "あなたは企業の技術文書検索アシスタントです。提供された文書に基づいて、構造化された回答を生成してください。"
},
{
"role": "user",
"content": f"質問: {query}\n\n参照文書:\n{context}"
}
],
response_format={
"type": "json_object",
"schema": DocumentAnswer.model_json_schema()
}
)
result = json.loads(response.choices[0].message.content)
return DocumentAnswer(**result)
def batch_search(self, queries: List[str], retrieved_docs: List[List[dict]]) -> List[DocumentAnswer]:
"""複数クエリのバッチ処理"""
results = []
for query, docs in zip(queries, retrieved_docs):
try:
result = self.search_and_answer(query, docs)
results.append(result)
except Exception as e:
print(f"クエリ処理エラー '{query[:30]}...': {e}")
results.append(None)
return results
使用例
system = DocumentQuerySystem()
sample_docs = [
{"page": 5, "content": "APIエンドポイントの設定方法はconfig.yamlで行います。"},
{"page": 12, "content": "認証はBearerトークンを使用し、有効期限は24時間です。"}
]
result = system.search_and_answer("APIの認証方法は?", sample_docs)
print(f"回答: {result.answer_summary}")
print(f"信頼度: {result.confidence_score}")
ベストプラクティス:レイテンシとコスト最適化
私自身、個人開発でSlack連携のBotを構築した際、毎秒数十件の問い合わせを處理する必要がありました。HolySheep AIの<50msレイテンシとDeepSeek V3.2の低価格は、このユースケースに完美にマッチしていました。
1. streaming対応の有効活用
import openai
client = openai.OpenAI(
api_key="YOUR_HOLYSHEEP_API_KEY",
base_url="https://api.holysheep.ai/v1"
)
Streaming対応でレスポンスタイムを短縮
stream_response = client.chat.completions.create(
model="deepseek-chat",
messages=[
{"role": "system", "content": "構造化されたJSONを返してください"},
{"role": "user", "content": "日本の首都について教えてください"}
],
stream=True,
response_format={"type": "json_object"}
)
チャンク単位で処理
for chunk in stream_response:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
2. Batch APIの活用(コスト削減)
処理량이 많은 경우、Batch APIを使用することでコストを大幅に削減できます。2026年現在の価格比較では、DeepSeek V3.2は$0.42/MTokと競争力があります。
よくあるエラーと対処法
エラー1: Invalid JSON Schema - 不完全なスキーマ定義
# ❌ エラー発生例:requiredフィールドの指定が不適切
bad_schema = {
"type": "object",
"properties": {
"result": {"type": "string"}
}
# requiredが欠落
}
✅ 修正版:requiredフィールドを明示的に指定
good_schema = {
"type": "object",
"properties": {
"result": {"type": "string"},
"status_code": {"type": "integer", "minimum": 100, "maximum": 599}
},
"required": ["result", "status_code"] # 必須フィールドを明示
}
スキーマ検証辅助関数
def validate_schema(schema: dict) -> bool:
"""スキーマの基本検証"""
required_fields = ["type", "properties", "required"]
for field in required_fields:
if field not in schema:
print(f"スキーマエラー: {field}フィールドが必要です")
return False
return True
エラー2: Function Calling時のtool_choice設定ミス
# ❌ エラー:tool_choiceに無効な値を指定
response = client.chat.completions.create(
model="deepseek-chat",
messages=messages,
tools=functions,
tool_choice="invalid_option" # "auto", "required", "none" のみ有効
)
✅ 修正版:正しいtool_choiceオプションを使用
response = client.chat.completions.create(
model="deepseek-chat",
messages=messages,
tools=functions,
tool_choice="auto" # 自動選択(推奨)
)
特定の関数を強制呼び出ししたい場合
response = client.chat.completions.create(
model="deepseek-chat",
messages=messages,
tools=functions,
tool_choice={"type": "function", "function": {"name": "get_order_status"}}
)
エラー处理的ラッパー関数
def safe_function_call(messages: list, functions: list, force_function: str = None):
"""Function Callingを安全に使用するラッパー"""
try:
tool_choice = "auto"
if force_function:
tool_choice = {"type": "function", "function": {"name": force_function}}
return client.chat.completions.create(
model="deepseek-chat",
messages=messages,
tools=functions,
tool_choice=tool_choice
)
except openai.BadRequestError as e:
print(f"リクエストエラー: {e}")
return None
except Exception as e:
print(f"予期しないエラー: {e}")
return None
エラー3: レートリミット超過(Rate Limit Exceeded)
import time
import asyncio
from collections import deque
class RateLimiter:
"""シンプルなトークンバケット方式のレ이트リミッター"""
def __init__(self, requests_per_minute: int = 60):
self.rpm = requests_per_minute
self.request_times = deque()
def wait_if_needed(self):
"""必要に応じて待機"""
now = time.time()
# 1分以内のリクエストをクリア
while self.request_times and self.request_times[0] < now - 60:
self.request_times.popleft()
if len(self.request_times) >= self.rpm:
# 最も古いリクエストが期限切れになるまで待機
sleep_time = 60 - (now - self.request_times[0])
print(f"レートリミット待機中: {sleep_time:.2f}秒")
time.sleep(sleep_time)
self.request_times.append(time.time())
async def async_wait_if_needed(self):
"""非同期版のレートリミッター"""
await asyncio.sleep(0.1) # API呼び出し間の最小間隔
self.wait_ifNeeded()
使用例
limiter = RateLimiter(requests_per_minute=60)
def api_call_with_rate_limit(user_message: str):
"""レートリミット対応のAPI呼び出し"""
limiter.wait_if_needed()
response = client.chat.completions.create(
model="deepseek-chat",
messages=[{"role": "user", "content": user_message}],
response_format={"type": "json_object"}
)
return response.choices[0].message.content
連続呼び出しの例
for i in range(5):
result = api_call_with_rate_limit(f"クエリ{i+1}: テストメッセージ")
print(f"リクエスト{i+1}完了")
エラー4: response_formatとtoolsの競合
# ❌ エラー:toolsとresponse_formatの同時指定がサポート外の場合がある
response = client.chat.completions.create(
model="deepseek-chat",
messages=messages,
tools=functions,
response_format={"type": "json_object"} # tools使用時は無効の場合がある
)
✅ 修正版:Function Calling結果からJSONを生成
def structured_function_call(messages: list, functions: list):
"""Function Callingで構造化されたデータを取得"""
# Step 1: Function Callingを実行
response = client.chat.completions.create(
model="deepseek-chat",
messages=messages,
tools=functions
)
message = response.choices[0].message
# Step 2: 関数が呼び出された場合の处理
if message.tool_calls:
tool_call = message.tool_calls[0]
function_name = tool_call.function.name
arguments = json.loads(tool_call.function.arguments)
# 関数の実際の処理结果を返す
return {
"function_called": function_name,
"arguments": arguments,
"finish_reason": message.finish_reason
}
# Step 3: 直接返答の場合、JSONオブジェクトとしてパース
return json.loads(message.content)
使用例
messages = [
{"role": "system", "content": "関数を適切に使用してください"},
{"role": "user", "content": "注文A12345の状況を確認"}
]
result = structured_function_call(messages, functions)
まとめ
DeepSeek V4の構造化出力とFunction Callingを組み合わせることで、信頼性の高いAIアプリケーションを構築できます。本稿で示した最佳実践を活用し、ECサイトのカスタマーサポート、RAGシステム、ボット開発など 다양한ユースケースに対応しましょう。
HolySheep AIは、WeChat PayやAlipayにも対応しており、海外在住の開発者でも簡単に 결제할 수 있습니다。今すぐ登録して無料クレジットを獲得し、高性能・低コストなDeepSeek V4を体験してみてください。
2026年現在の市场价格比較においても、DeepSeek V3.2の$0.42/MTokという価格は大幅に低く、最大85%のコスト節約を実現できます。
👉 HolySheep AI に登録して無料クレジットを獲得