mcpField
G
genai-services

genai-services

github.com/acedergrenクラウド・DevOps2289 回インストール33 週間前に更新
リポジトリ

genai-services について

OCI Generative AIサービスの実装と運用に関するリファレンススキルです。モデル選定、トークンとコストの管理、レート制限、応答検証を扱い、医療データやコンプライアンス要件を扱う開発者やチームを対象とします。

主な機能

  1. 01OCIモデル選定の指針
  2. 02トークンとコストの最適化
  3. 03レート制限への再試行パターン
  4. 04PHI/PIIのマスキング指針
  5. 05応答検証と監査

活用シーン

  1. 01GenAIサービスのコスト見積もり
  2. 02トークン制限やレート制限エラーへの対処
  3. 03医療データのマスキング設計
  4. 04利用前の生成応答の検証

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/acedergren/oci-agent-skills --skill genai-services

インストール後、Claude Code で/genai-servicesを入力して読み込まれたか確認します。

同梱ファイルmetadata.jsonreferences/oci-genai-reference.md

詳細

OCI Generative AI サービス - 専門知識

🏗️ OCI Landing Zone Terraform モジュールを使用する

車輪の再発明はしないでください。 GenAI インフラストラクチャには oracle-terraform-modules/landing-zone を使用してください。

Landing Zone で解決できること:

  • ❌ 悪いプラクティス #1:汎用的なコンパートメント(Landing Zone は AI/ML ワークロード用のコンパートメントを作成します)
  • ❌ 悪いプラクティス #4:不十分なセグメンテーション(Landing Zone は GenAI エンドポイントをプライベートサブネットに隔離します)
  • ❌ 悪いプラクティス #10:監視機能がない(Landing Zone は GenAI の使用状況アラームを設定します)

このスキルが提供するもの:Landing Zone 内にデプロイされた GenAI のコスト最適化、レート制限、PHI/PII セキュリティ、トラブルシューティング。


⚠️ OCI CLI/API に関する知識の不足

OCI CLI コマンドや OCI API の構造については把握していません。

トレーニングデータに含まれる以下の情報は限られており、古くなっている可能性があります。

  • OCI CLI の構文とパラメーター(毎月更新されます)
  • OCI GenAI API のエンドポイントとリクエスト/レスポンス形式
  • GenAI サービスの CLI 操作(oci generative-ai)
  • 利用可能なモデル、トークン制限、料金(頻繁に変更されます)
  • 最新の GenAI 機能(Agents、RAG)と API の変更

OCI の操作が必要な場合:

  1. このスキルのリファレンスに記載された正確な CLI コマンドを使用してください
  2. OCI CLI の構文やパラメーターを推測しないでください
  3. モデルの提供状況や料金を決めつけないでください
  4. 詳細な GenAI API ドキュメントについては、リファレンスファイルを読み込んでください

把握していること:

  • LLM の一般的な概念とプロンプトのパターン
  • トークンの推定とコンテキスト管理
  • API 統合のパターン

このスキルは、OCI GenAI 固有の最新パターンや注意点を提供することで、この不足を補います。


あなたは OCI GenAI のエキスパートです。このスキルは、Claude が把握していないコスト最適化の詳細、トークン管理、レート制限への対応、PHI/PII セキュリティ、レスポンスの検証、モデル選択におけるトレードオフに関する知識を提供します。

絶対にしてはいけないこと

❌ GenAI API に PHI/PII 識別子を絶対に送信しないでください(HIPAA/GDPR 違反)

# WRONG - patient identifiers sent to external service
prompt = f"Transcribe note for patient {patient_name}, MRN {mrn}, SSN {ssn}: {note}"

# RIGHT - redact identifiers
prompt = f"Transcribe this medical note: {redacted_note}"
# Keep mapping: temp_id → real_id in secure database, not in prompts

重大な理由:GenAI サービスのログにデータが保持される可能性があり、医療関連の規制に違反します

❌ 検証せずに GenAI の出力を絶対に信頼しないでください(ハルシネーションのリスク)

# WRONG - use response directly in critical systems
diagnosis = genai_response.text
db.execute("UPDATE patients SET diagnosis = ?", diagnosis)

# RIGHT - validate structure and flag for human review
response = genai_response.text
if validate_medical_format(response):
    db.execute("UPDATE patients SET ai_suggested_diagnosis = ?, status = 'PENDING_REVIEW'", response)

ハルシネーション率:事実に関する質問では 5~15%、医療や法律の分野ではさらに高くなります

❌ トークン制限を絶対に無視しないでください

  • command-r-plus:128k のコンテキストウィンドウ(入力+出力)
  • command-r:4k のコンテキスト(大幅に安価ですが制限があります)
  • 制限超過時:リクエストが通知なく切り詰められるか、400 エラーで失敗します

❌ レート制限への対応なしに GenAI を絶対に呼び出さないでください

# WRONG - no retry logic, fails on rate limit
response = genai_client.chat(request)

# RIGHT - exponential backoff
def call_with_retry(func, max_retries=5):
    for attempt in range(max_retries):
        try:
            return func()
        except oci.exceptions.ServiceError as e:
            if e.status == 429 and attempt < max_retries - 1:
                wait = (2 ** attempt) + random.uniform(0, 1)
                logger.warning(f"Rate limited, retry in {wait:.2f}s")
                time.sleep(wait)
            else:
                raise

❌ 同意なしにレスポンスを絶対にキャッシュしないでください(データプライバシー)

  • キャッシュはコストを削減しますが、プライバシーポリシーに違反する可能性があります
  • 医療データや個人データをキャッシュする前に、ユーザーの明示的な同意を得てください
  • 匿名化されたデータのみをキャッシュしてください

❌ 決定論的なタスクに GenAI を絶対に使用しないでください

  • 不適切:「OCR テキストから請求書の合計金額を抽出する」(正規表現/構造化解析を使用してください)
  • 不適切:「メールアドレスの形式を検証する」(検証ライブラリを使用してください)
  • 適切:「患者の病歴を要約する」「レポートの説明文を生成する」(創造的なタスク)

モデルの選択:コストと性能

モデルコンテキストコスト(100 万トークンあたり)最適な用途避けるべき用途
command-r-plus128k~$15 入力、$75 出力複雑な推論、長文書単純なタスク(高コスト)
command-r4k~$1.50 入力、$7.50 出力チャット、短いプロンプト、大量処理長文書、RAG
embed-english-v3該当なし100 万あたり約 $0.10セマンティック検索、クラスタリングテキスト生成
llama-2-70b4k~$2 入力、$10 出力オープンウェイト、コスト効率本番環境(サポートが限定的)

コスト最適化の戦略:

  1. まず検索には埋め込みを使用する(生成より 1000 倍安価)
  2. 繰り返しのクエリに対するレスポンスをキャッシュする(同意を得たうえで)
  3. 単純なタスクには command-r を使用し、必要な場合にのみ command-r-plus を使用する
  4. 入力を適切に切り詰める(関連するコンテキストのみを残す)

コスト計算の例

シナリオ:医療文字起こしサービス

  • 平均的なメモ:入力500トークン、出力300トークン=合計800トークン
  • 1日あたり1000件のメモ=1日あたり800kトークン=1か月あたり24Mトークン

最適化なしの場合:

Model: command-r-plus
Input:  12M × ($15/1M) = $180/month
Output: 12M × ($75/1M) = $900/month
Total: $1,080/month

最適化ありの場合(キャッシュヒット率30%、簡単なメモには command-r を使用):

70% unique notes = 16.8M tokens
60% simple (command-r): 10M × $1.50 input + $7.50 output = $90
40% complex (command-r-plus): 6.72M × $15 input + $75 output = $605
Total: $695/month (36% savings)

トークン管理

モデルごとのトークン制限
モデル最大コンテキスト最大出力備考
command-r-plus128k(入力+出力)変動約4文字で1トークン(概算)
command-r4k2kチャットに適しています
embed-english-v3512該当なし埋め込みのみ
切り捨て戦略
def truncate_for_model(text: str, model: str = "command-r-plus", max_output: int = 2000):
    """Truncate input to fit token budget"""

    # Rough estimate: 1 token ≈ 4 characters
    if model == "command-r-plus":
        max_input_tokens = 128000 - max_output
    elif model == "command-r":
        max_input_tokens = 4000 - max_output
    else:
        max_input_tokens = 2000

    max_chars = max_input_tokens * 4

    if len(text) <= max_chars:
        return text

    # Keep most recent content (chronological data like logs, notes)
    logger.warning(f"Input exceeds {max_input_tokens} tokens, truncating")
    return "...[earlier content truncated]...\n" + text[-max_chars:]
プロンプトの最適化

非効率(トークンを浪費):

Please carefully analyze the following medical record and provide a comprehensive
summary including all diagnoses, medications, allergies, and treatment plans. Be
thorough and include all relevant details from the patient's history...

[5000 word medical record]

最適化済み(トークンを40%削減):

Summarize: diagnoses, meds, allergies, treatment plan.

[5000 word medical record]

トークンの節約量:プロンプトあたり約50トークン × 1日あたり1000リクエスト=1日あたり50kトークンを節約=$2.25/日($68/月)

レート制限

OCI GenAI サービスの制限(コンパートメントあたり):
モデル1分あたりのリクエスト数1日あたりのリクエスト数リクエストあたりのトークン数
command-r-plus201000128k
command-r6030004k
埋め込み10010000512
エラー処理
import time
import random
from oci.exceptions import ServiceError

def generate_with_backoff(genai_client, request, max_retries=5):
    """Call GenAI with exponential backoff on rate limits"""

    for attempt in range(max_retries):
        try:
            response = genai_client.chat(request)
            return response.data.chat_response.text

        except ServiceError as e:
            if e.status == 429:  # Rate limit
                if attempt < max_retries - 1:
                    # Exponential backoff: 1s, 2s, 4s, 8s, 16s
                    wait = (2 ** attempt) + random.uniform(0, 1)
                    logger.warning(f"Rate limited (429), retry {attempt+1}/{max_retries} in {wait:.1f}s")
                    time.sleep(wait)
                else:
                    logger.error(f"Rate limit exceeded after {max_retries} retries")
                    raise

            elif e.status == 400:  # Bad request (often token limit)
                logger.error(f"Bad request (400): {e.message}")
                if "token" in e.message.lower():
                    logger.error("Token limit exceeded - truncate input")
                raise

            else:
                logger.error(f"GenAI error ({e.status}): {e.message}")
                raise

レスポンスの検証(医療分野では重要)

def validate_medical_response(response: str) -> tuple[bool, list[str]]:
    """Validate GenAI medical response for safety"""

    issues = []

    # Check 1: Response not empty
    if not response or len(response.strip()) < 10:
        issues.append("Response too short or empty")

    # Check 2: No obvious hallucination markers
    hallucination_markers = [
        "I don't have access",
        "I cannot",
        "As an AI",
        "[INSERT",
        "TODO",
    ]
    for marker in hallucination_markers:
        if marker.lower() in response.lower():
            issues.append(f"Potential hallucination marker: {marker}")

    # Check 3: Expected structure present (customize per use case)
    required_sections = ["Chief Complaint", "Assessment", "Plan"]
    missing_sections = [s for s in required_sections if s.lower() not in response.lower()]
    if missing_sections:
        issues.append(f"Missing sections: {missing_sections}")

    # Check 4: No PII leak (if input was redacted)
    pii_patterns = [
        r'\b\d{3}-\d{2}-\d{4}\b',  # SSN
        r'\b[A-Z]{2}\d{6,8}\b',     # MRN patterns
    ]
    for pattern in pii_patterns:
        if re.search(pattern, response):
            issues.append(f"Potential PII in response: {pattern}")

    is_valid = len(issues) == 0
    return is_valid, issues


# Usage
response_text = genai_response.data.chat_response.text
is_valid, issues = validate_medical_response(response_text)

if is_valid:
    store_for_review(response_text)
else:
    logger.warning(f"Invalid response: {issues}")
    flag_for_manual_review(response_text, issues)

医療分野固有の考慮事項

HIPAA 準拠

最低限の要件:

  • ✅ Oracle との業務提携契約(BAA)
  • ✅ GenAI に送信する前に PHI をマスキングする
  • ✅ すべての GenAI API 呼び出しを監査ログに記録する
  • ✅ 転送中および保存時の暗号化
  • ✅ アクセス制御(GenAI を呼び出せるユーザー)
  • ✅ データ保持ポリシー(プロンプト/レスポンスの保持期間)

GenAI がデフォルトで HIPAA に準拠していると決して想定しないでください — Oracle に BAA の適用範囲を確認してください

匿名化戦略
def redact_phi(text: str) -> tuple[str, dict]:
    """Remove PHI from text, return redacted text + mapping"""

    mapping = {}
    redacted = text

    # Patient names (use NER or pattern matching)
    names = extract_names(text)  # Your NER function
    for i, name in enumerate(names):
        placeholder = f"[PATIENT_{i}]"
        mapping[placeholder] = name
        redacted = redacted.replace(name, placeholder)

    # Medical Record Numbers
    mrn_pattern = r'\b(MRN|Medical Record):?\s*([A-Z0-9]{6,10})\b'
    redacted = re.sub(mrn_pattern, r'\1: [REDACTED]', redacted)

    # SSN
    ssn_pattern = r'\b\d{3}-\d{2}-\d{4}\b'
    redacted = re.sub(ssn_pattern, '[SSN_REDACTED]', redacted)

    # Dates (optional - some use cases need dates)
    # date_pattern = r'\b\d{1,2}/\d{1,2}/\d{4}\b'
    # redacted = re.sub(date_pattern, '[DATE]', redacted)

    return redacted, mapping


# Usage
redacted_note, phi_mapping = redact_phi(patient_note)
genai_response = genai_client.chat(prompt=f"Summarize: {redacted_note}")
# Store phi_mapping securely, use to re-identify if needed

段階的な読み込みに関するリファレンス

OCI Generative AI のリファレンス(Oracle 公式ドキュメント)

次の場合に読み込みます oci-genai-reference.md:

  • GenAI API の包括的なドキュメントが必要な場合
  • 利用可能なすべてのモデルと機能を把握する場合
  • OCI を使用して RAG(検索拡張生成)を実装する場合
  • GenAI Agents に関する Oracle 公式のガイダンスが必要な場合
  • ファインチューニングとカスタムモデルのデプロイについて理解する場合

次の場合は読み込まないでください:

  • API の簡単な使用例を確認する場合(このスキルで説明しています)
  • モデル選択のガイダンスを確認する場合(上記の判断フローを参照)
  • コストを計算する場合(上記の計算式を参照)

このスキルを使用する場面

  • GenAI API の実装:モデル選択、コスト見積もり、SDK の使用
  • エラーのトラブルシューティング:レート制限(429)、トークン制限(400)、認証
  • コストの最適化:キャッシュ戦略、モデルのダウングレード、プロンプトの最適化
  • 医療/コンプライアンス:PHI の取り扱い、HIPAA の要件、監査ログ
  • レスポンスの検証:幻覚の検出、構造のチェック
  • 本番環境:レート制限への対応、エラーからの復旧、モニタリング

コメント