Agent Skills by ALSEL
汎用LLM・AI開発⭐ リポ 3,980品質スコア 90/100

openrag_sdk

OpenRAG SDKをアプリケーションに統合する際に、コード例、設定方法、ベストプラクティスを用いて開発者をガイドします。統合プロセスの各段階をサポートし、正しい実装方法を示すことで、スムーズで効率的なセットアップを実現できます。

description の原文を見る

Guide developers through integrating the OpenRAG SDK into applications with code examples, configuration, and best practices

SKILL.md 本文

ユーザーが OpenRAG SDK を統合するか、アプリケーションで OpenRAG を使用するよう依頼した場合は、このワークフローに従ってください。

初期評価フェーズ

SDK 統合を始める前に:

  1. OpenRAG インスタンスを識別します:
    • ベース URL を決定します(例:http://localhost:3000https://api.example.com
    • 認証が必要かどうかを確認します(API キー)
    • API の可用性をテストします:curl <base_url> または curl <base_url>/health
  2. ターゲットアプリケーションを識別します:
    • プログラミング言語(Python、JavaScript/TypeScript)
    • フレームワーク(存在する場合):FastAPI、Flask、Express、React、Next.js など
    • プロジェクト構造と既存の依存関係
  3. 統合要件を決定します:
    • RAG チャット機能(ストリーミングまたは非ストリーミング)
    • セマンティック検索
    • ドキュメント取り込みと管理
    • ナレッジフィルター
    • 会話履歴管理
    • 設定管理

主な目標

  • ターゲット言語に適切な SDK パッケージをインストールする
  • 認証と接続設定を構成する
  • 動作するコード例を使用してコア機能を実装する
  • 適切なエラーハンドリングを追加する
  • 統合をローカルでテストする
  • メンテナンスのための統合ドキュメントを作成する

SDK インストール

Python SDK

パッケージ: openrag-sdk

インストール:

pip install openrag-sdk

または uv で:

uv add openrag-sdk

TypeScript/JavaScript SDK

パッケージ: openrag-sdk

インストール:

npm install openrag-sdk

または他のパッケージマネージャーで:

yarn add openrag-sdk
pnpm add openrag-sdk
bun add openrag-sdk

MCP サーバー

パッケージ: openrag-mcp

MCP 統合(Model Context Protocol)の場合:

pip install openrag-mcp

または uvx で:

uvx openrag-mcp

設定

Python SDK 設定

SDK は環境変数またはコンストラクター引数を通じて設定できます:

環境変数:

OPENRAG_API_KEY=your-api-key  # 認証が有効な場合は必須
OPENRAG_URL=http://localhost:3000  # オプション、デフォルトは localhost:3000

コンストラクター引数:

from openrag_sdk import OpenRAGClient

# 環境変数を使用(OPENRAG_API_KEY と OPENRAG_URL を自動検出)
client = OpenRAGClient()

# 明示的な引数を使用
client = OpenRAGClient(
    api_key="orag_...",
    base_url="https://api.example.com"
)

TypeScript SDK 設定

TypeScript の同様の設定オプション:

import { OpenRAGClient } from 'openrag-sdk';

// 環境変数を使用
const client = new OpenRAGClient();

// 明示的な設定を使用
const client = new OpenRAGClient({
  apiKey: 'orag_...',
  baseUrl: 'https://api.example.com'
});

コア機能の例

1. チャット(非ストリーミング)

Python:

import asyncio
from openrag_sdk import OpenRAGClient

async def main():
    # クライアントは環境から OPENRAG_API_KEY と OPENRAG_URL を自動検出
    async with OpenRAGClient() as client:
        # シンプルなチャット
        response = await client.chat.create(message="What is RAG?")
        print(response.response)
        print(f"Chat ID: {response.chat_id}")
        
        # 会話を続ける
        followup = await client.chat.create(
            message="Tell me more",
            chat_id=response.chat_id
        )
        print(followup.response)

asyncio.run(main())

TypeScript:

import { OpenRAGClient } from 'openrag-sdk';

async function main() {
  const client = new OpenRAGClient();
  
  // シンプルなチャット
  const response = await client.chat.create({
    message: "What is RAG?"
  });
  console.log(response.response);
  console.log(`Chat ID: ${response.chatId}`);
  
  // 会話を続ける
  const followup = await client.chat.create({
    message: "Tell me more",
    chatId: response.chatId
  });
  console.log(followup.response);
}

main();

2. チャット(ストリーミング)

Python:

async def streaming_chat():
    chat_id = None
    async with OpenRAGClient() as client:
        # レスポンスをストリーム処理
        async for event in await client.chat.create(
            message="Explain RAG", 
            stream=True
        ):
            if event.type == "content":
                print(event.delta, end="", flush=True)
            elif event.type == "sources":
                for source in event.sources:
                    print(f"\nSource: {source.filename}")
            elif event.type == "done":
                chat_id = event.chat_id

asyncio.run(streaming_chat())

stream() コンテキストマネージャーを使用した Python:

async def streaming_with_context():
    async with OpenRAGClient() as client:
        # 完全なイベント反復
        async with client.chat.stream(message="Explain RAG") as stream:
            async for event in stream:
                if event.type == "content":
                    print(event.delta, end="", flush=True)
        
        # 反復後に集計されたデータにアクセス
        print(f"\nChat ID: {stream.chat_id}")
        
        # 最終テキストを直接取得
        async with client.chat.stream(message="Explain RAG") as stream:
            text = await stream.final_text()
            print(text)

asyncio.run(streaming_with_context())

TypeScript:

async function streamingChat() {
  const client = new OpenRAGClient();
  
  const stream = await client.chat.create({
    message: "Explain RAG",
    stream: true
  });
  
  for await (const event of stream) {
    if (event.type === 'content') {
      process.stdout.write(event.delta);
    } else if (event.type === 'sources') {
      for (const source of event.sources) {
        console.log(`\nSource: ${source.filename}`);
      }
    } else if (event.type === 'done') {
      console.log(`\nChat ID: ${event.chatId}`);
    }
  }
}

3. 会話履歴

Python:

async def manage_conversations():
    async with OpenRAGClient() as client:
        # すべての会話をリスト表示
        conversations = await client.chat.list()
        for conv in conversations.conversations:
            print(f"{conv.chat_id}: {conv.title}")
        
        if not conversations.conversations:
            print("No conversations found")
            return
        
        chat_id = conversations.conversations[0].chat_id
        
        # メッセージ付きの特定の会話を取得
        conversation = await client.chat.get(chat_id)
        for msg in conversation.messages:
            print(f"{msg.role}: {msg.content}")
        
        # 会話を削除
        await client.chat.delete(chat_id)

asyncio.run(manage_conversations())

TypeScript:

async function manageConversations() {
  const client = new OpenRAGClient();
  
  // すべての会話をリスト表示
  const conversations = await client.chat.list();
  for (const conv of conversations.conversations) {
    console.log(`${conv.chatId}: ${conv.title}`);
  }
  
  if (!conversations.conversations.length) {
    console.log("No conversations found");
    return;
  }
  
  const chatId = conversations.conversations[0].chatId;
  
  // 特定の会話を取得
  const conversation = await client.chat.get(chatId);
  for (const msg of conversation.messages) {
    console.log(`${msg.role}: ${msg.content}`);
  }
  
  // 会話を削除
  await client.chat.delete(chatId);
}

4. 検索

Python:

async def search_knowledge():
    async with OpenRAGClient() as client:
        # 基本的な検索
        results = await client.search.query("document processing")
        for result in results.results:
            print(f"{result.filename} (score: {result.score})")
            print(f"{result.text[:100]}...")
        
        # フィルター付き検索
        from openrag_sdk import SearchFilters
        
        results = await client.search.query(
            "API documentation",
            filters=SearchFilters(
                data_sources=["api-docs.pdf"],
                document_types=["application/pdf"]
            ),
            limit=5,
            score_threshold=0.5
        )

asyncio.run(search_knowledge())

TypeScript:

async function searchKnowledge() {
  const client = new OpenRAGClient();
  
  // 基本的な検索
  const results = await client.search.query("document processing");
  
  for (const result of results.results) {
    console.log(`${result.filename} (score: ${result.score})`);
    console.log(`${result.text.substring(0, 100)}...`);
  }
  
  // フィルター付き検索
  const filtered = await client.search.query("API documentation", {
    filters: {
      data_sources: ["api-docs.pdf"],
      document_types: ["application/pdf"]
    },
    limit: 5,
    scoreThreshold: 0.5
  });
}

5. ドキュメント管理

Python:

async def manage_documents():
    async with OpenRAGClient() as client:
        # ファイルを取り込み(デフォルトで完了を待機)
        result = await client.documents.ingest(file_path="./report.pdf")
        print(f"Status: {result.status}")
        
        # ファイルオブジェクトから取り込み
        with open("./report.pdf", "rb") as f:
            result = await client.documents.ingest(file=f, filename="report.pdf")
        
        # 完了を手動でポーリング
        final_status = await client.documents.wait_for_task(result.task_id)
        print(f"Status: {final_status.status}")
        print(f"Successful files: {final_status.successful_files}")
        
        # ドキュメントを削除
        result = await client.documents.delete("report.pdf")
        print(f"Success: {result.success}")

asyncio.run(manage_documents())

TypeScript:

async function manageDocuments() {
  const client = new OpenRAGClient();
  
  // ファイルを取り込み
  const result = await client.documents.ingest({
    filePath: "./report.pdf"
  });
  console.log(`Status: ${result.status}`);
  
  // 完了をポーリング
  const finalStatus = await client.documents.waitForTask(result.task_id);
  console.log(`Status: ${finalStatus.status}`);
  console.log(`Successful files: ${finalStatus.successful_files}`);
  
  // ドキュメントを削除
  const deleteResult = await client.documents.delete("report.pdf");
  console.log(`Success: ${deleteResult.success}`);
}

6. 設定管理

Python:

async def manage_settings():
    async with OpenRAGClient() as client:
        # 設定を取得
        settings = await client.settings.get()
        print(f"LLM Provider: {settings.agent.llm_provider}")
        print(f"LLM Model: {settings.agent.llm_model}")
        print(f"Embedding Model: {settings.knowledge.embedding_model}")
        
        # 設定を更新
        await client.settings.update({
            "llm_provider": "openai",
            "llm_model": "gpt-4o",
            "embedding_provider": "openai",
            "embedding_model": "text-embedding-3-small"
        })

asyncio.run(manage_settings())

TypeScript:

async function manageSettings() {
  const client = new OpenRAGClient();
  
  // 設定を取得
  const settings = await client.settings.get();
  console.log(`LLM Provider: ${settings.agent.llmProvider}`);
  console.log(`LLM Model: ${settings.agent.llmModel}`);
  
  // 設定を更新
  await client.settings.update({
    llm_provider: "openai",
    llm_model: "gpt-4o",
    embedding_provider: "openai",
    embedding_model: "text-embedding-3-small"
  });
}

7. ナレッジフィルター

Python:

async def use_knowledge_filters():
    async with OpenRAGClient() as client:
        # ナレッジフィルターを作成
        result = await client.knowledge_filters.create({
            "name": "Technical Docs",
            "description": "Filter for technical documentation",
            "queryData": {
                "query": "technical",
                "filters": {
                    "document_types": ["application/pdf"]
                },
                "limit": 10,
                "scoreThreshold": 0.5
            }
        })
        filter_id = result.id
        
        # フィルターを検索
        filters = await client.knowledge_filters.search("Technical")
        for f in filters:
            print(f"{f.name}: {f.description}")
        
        # フィルターを更新
        await client.knowledge_filters.update(filter_id, {
            "description": "Updated description"
        })
        
        # フィルターを削除
        await client.knowledge_filters.delete(filter_id)
        
        # チャットでフィルターを使用
        response = await client.chat.create(
            message="Explain the API",
            filter_id=filter_id
        )
        
        # 検索でフィルターを使用
        results = await client.search.query(
            "API endpoints",
            filter_id=filter_id
        )

asyncio.run(use_knowledge_filters())

TypeScript:

async function useKnowledgeFilters() {
  const client = new OpenRAGClient();
  
  // ナレッジフィルターを作成
  const result = await client.knowledgeFilters.create({
    name: "Technical Docs",
    description: "Filter for technical documentation",
    queryData: {
      query: "technical",
      filters: {
        documentTypes: ["application/pdf"]
      },
      limit: 10,
      scoreThreshold: 0.5
    }
  });
  const filterId = result.id;
  
  // チャットでフィルターを使用
  const response = await client.chat.create({
    message: "Explain the API",
    filterId: filterId
  });
  
  // 検索でフィルターを使用
  const results = await client.search.query({
    query: "API endpoints",
    filterId: filterId
  });
}

エラーハンドリング

Python エラーハンドリング

from openrag_sdk import (
    OpenRAGError,
    AuthenticationError,
    NotFoundError,
    ValidationError,
    RateLimitError,
    ServerError
)

async def handle_errors():
    try:
        async with OpenRAGClient() as client:
            response = await client.chat.create(message="Hello")
    except AuthenticationError as e:
        print(f"Invalid API key: {e.message}")
    except NotFoundError as e:
        print(f"Resource not found: {e.message}")
    except ValidationError as e:
        print(f"Invalid request: {e.message}")
    except RateLimitError as e:
        print(f"Rate limited: {e.message}")
    except ServerError as e:
        print(f"Server error: {e.message} (status: {e.status_code})")
    except OpenRAGError as e:
        print(f"API error: {e.message} (status: {e.status_code})")

TypeScript エラーハンドリング

import {
  OpenRAGClient,
  OpenRAGError,
  AuthenticationError,
  NotFoundError,
  ValidationError,
  RateLimitError,
  ServerError
} from 'openrag-sdk';

async function handleErrors() {
  try {
    const client = new OpenRAGClient();
    const response = await client.chat.create({ message: "Hello" });
  } catch (error) {
    if (error instanceof AuthenticationError) {
      console.error(`Invalid API key: ${error.message}`);
    } else if (error instanceof NotFoundError) {
      console.error(`Resource not found: ${error.message}`);
    } else if (error instanceof ValidationError) {
      console.error(`Invalid request: ${error.message}`);
    } else if (error instanceof RateLimitError) {
      console.error(`Rate limited: ${error.message}`);
    } else if (error instanceof ServerError) {
      console.error(`Server error: ${error.message}`);
    } else if (error instanceof OpenRAGError) {
      console.error(`API error: ${error.message}`);
    }
  }
}

統合パターン

パターン 1: FastAPI バックエンド

from fastapi import FastAPI, HTTPException
from openrag_sdk import OpenRAGClient
from pydantic import BaseModel

app = FastAPI()
client = OpenRAGClient()

class ChatRequest(BaseModel):
    message: str
    chat_id: str | None = None

@app.post("/api/chat")
async def chat(request: ChatRequest):
    try:
        response = await client.chat.create(
            message=request.message,
            chat_id=request.chat_id
        )
        return {
            "answer": response.response,
            "sources": [{"filename": s.filename, "score": s.score} for s in response.sources],
            "chat_id": response.chat_id
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/api/search")
async def search(query: str, limit: int = 10):
    try:
        results = await client.search.query(query, limit=limit)
        return {
            "results": [
                {
                    "filename": r.filename,
                    "text": r.text,
                    "score": r.score
                }
                for r in results.results
            ]
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

パターン 2: Express.js バックエンド

import express from 'express';
import { OpenRAGClient } from 'openrag-sdk';

const app = express();
const client = new OpenRAGClient();

app.use(express.json());

app.post('/api/chat', async (req, res) => {
  try {
    const { message, chatId } = req.body;
    const response = await client.chat.create({
      message,
      chatId
    });
    
    res.json({
      answer: response.response,
      sources: response.sources.map(s => ({
        filename: s.filename,
        score: s.score
      })),
      chatId: response.chatId
    });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.get('/api/search', async (req, res) => {
  try {
    const { query, limit = 10 } = req.query;
    const results = await client.search.query({
      query: query as string,
      limit: Number(limit)
    });
    
    res.json({
      results: results.results.map(r => ({
        filename: r.filename,
        text: r.text,
        score: r.score
      }))
    });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.listen(3001, () => {
  console.log('Server running on port 3001');
});

パターン 3: React フロントエンド

import { useState } from 'react';
import { OpenRAGClient } from 'openrag-sdk';

// 注意:本番環境では、API キーをブラウザで公開しないために
// バックエンド経由で API 呼び出しをプロキシしてください
const client = new OpenRAGClient({
  baseUrl: process.env.REACT_APP_OPENRAG_URL
});

function ChatComponent() {
  const [message, setMessage] = useState('');
  const [chatId, setChatId] = useState<string | null>(null);
  const [response, setResponse] = useState('');
  const [loading, setLoading] = useState(false);

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    setLoading(true);
    
    try {
      const result = await client.chat.create({
        message,
        chatId,
        limit: 5
      });
      
      setResponse(result.response);
      setChatId(result.chatId);
      setMessage('');
    } catch (error) {
      console.error('Chat error:', error);
    } finally {
      setLoading(false);
    }
  };

  return (
    <div>
      <form onSubmit={handleSubmit}>
        <input
          value={message}
          onChange={(e) => setMessage(e.target.value)}
          placeholder="Ask a question..."
          disabled={loading}
        />
        <button type="submit" disabled={loading}>
          {loading ? 'Sending...' : 'Send'}
        </button>
      </form>
      {response && (
        <div className="response">
          {response}
        </div>
      )}
    </div>
  );
}

パターン 4: React でのストリーミング

import { useState } from 'react';
import { OpenRAGClient } from 'openrag-sdk';

function StreamingChat() {
  const [message, setMessage] = useState('');
  const [response, setResponse] = useState('');
  const [streaming, setStreaming] = useState(false);
  const client = new OpenRAGClient();

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    setStreaming(true);
    setResponse('');
    
    try {
      const stream = await client.chat.create({
        message,
        stream: true
      });
      
      for await (const event of stream) {
        if (event.type === 'content') {
          setResponse(prev => prev + event.delta);
        }
      }
    } catch (error) {
      console.error('Streaming error:', error);
    } finally {
      setStreaming(false);
      setMessage('');
    }
  };

  return (
    <div>
      <form onSubmit={handleSubmit}>
        <input
          value={message}
          onChange={(e) => setMessage(e.target.value)}
          disabled={streaming}
        />
        <button type="submit" disabled={streaming}>
          {streaming ? 'Streaming...' : 'Send'}
        </button>
      </form>
      <div className="response">
        {response}
        {streaming && <span className="cursor"></span>}
      </div>
    </div>
  );
}

セキュリティベストプラクティス

  1. クライアント側のコードで API キーを公開しない

    • 常にバックエンド経由でリクエストをプロキシする
    • API キーに環境変数を使用する
    • バックエンドで適切な認証を実装する
  2. 本番環境で HTTPS を使用する

    • 本番デプロイメントには常に HTTPS を使用する
    • 適切な SSL/TLS 証明書を設定する
  3. 入力を検証とサニタイズする

    • OpenRAG に送信する前にユーザー入力を検証する
    • ユーザーに表示する前に出力をサニタイズする
    • エンドポイントにレート制限を実装する
  4. 適切なエラーハンドリングを実装する

    • エラーメッセージで機密情報を公開しない
    • デバッグのためにエラーをセキュアにログする
    • ユーザーにわかりやすいエラーメッセージを提供する
  5. OWASP ガイドラインに従う

    • 適切な認証と認可を実装する
    • 一般的な脆弱性から保護する(XSS、CSRF など)
    • 依存関係を最新に保つ

テスト戦略

Python テスト

import pytest
from openrag_sdk import OpenRAGClient

@pytest.fixture
async def client():
    async with OpenRAGClient() as client:
        yield client

@pytest.mark.asyncio
async def test_chat_basic(client):
    response = await client.chat.create(message="Hello")
    assert response.response is not None
    assert isinstance(response.sources, list)
    assert response.chat_id is not None

@pytest.mark.asyncio
async def test_search_with_filters(client):
    results = await client.search.query(
        "test",
        filters={"document_types": ["application/pdf"]}
    )
    assert isinstance(results.results, list)

TypeScript テスト

import { describe, it, expect } from 'vitest';
import { OpenRAGClient } from 'openrag-sdk';

describe('OpenRAG SDK', () => {
  const client = new OpenRAGClient();

  it('should chat successfully', async () => {
    const response = await client.chat.create({
      message: 'Hello'
    });
    
    expect(response.response).toBeDefined();
    expect(response.sources).toBeInstanceOf(Array);
    expect(response.chatId).toBeDefined();
  });

  it('should search with filters', async () => {
    const results = await client.search.query({
      query: 'test',
      filters: {
        documentTypes: ['application/pdf']
      }
    });
    
    expect(results.results).toBeInstanceOf(Array);
  });
});

トラブルシューティング

接続の問題

  • ベース URL が正しいことを確認します(例:http://localhost:3000 または https://api.example.com
  • 接続をテストします:curl <base_url> または curl <base_url>/health
  • OpenRAG がリモートサーバー上にある場合は、ネットワーク接続を確認します
  • ファイアウォールまたはネットワークポリシーが接続をブロックしていないことを確認します
  • ドメイン名を使用している場合は DNS 解決を確認します

認証エラー

  • 認証が有効な場合は、API キーが正しいことを確認します
  • API キーが環境変数で正しく設定されていることを確認します
  • API キーに必要な権限があることを確認します

パフォーマンス最適化

  • 適切な limit 値を使用します(必要以上のソースを取得しない)
  • 合理的な score_threshold を設定して低品質の結果をフィルターします
  • 頻繁に質問される質問のキャッシュを実装します
  • 高トラフィックアプリケーションではコネクションプーリングを使用します
  • より良いユーザー体験のためにストリーミングを使用することを検討します

レスポンス品質の問題

  • score_threshold を調整して関連性のない結果をフィルターします
  • より良いレスポンスのためにシステムプロンプトを確認して更新します
  • ナレッジベースに関連するドキュメントがあることを確認します
  • ドメイン固有のクエリにはナレッジフィルターを使用することを検討します

デプロイメント上の考慮事項

  1. 環境設定
    • 開発環境・ステージング環境・本番環境で異なる設定を使用する

ライセンス: Apache-2.0(寛容ライセンスのため全文を引用しています) · 原本リポジトリ

詳細情報

作者
langflow-ai
リポジトリ
langflow-ai/openrag
ライセンス
Apache-2.0
最終更新
2026/5/12

Source: https://github.com/langflow-ai/openrag / ライセンス: Apache-2.0

本サイトは GitHub 上で公開されているオープンソースの SKILL.md ファイルをクロール・インデックス化したものです。 各スキルの著作権は原作者に帰属します。掲載に問題がある場合は info@alsel.co.jp または /takedown フォームよりご連絡ください。
原作者: langflow-ai · langflow-ai/openrag · ライセンス: Apache-2.0