cortex-hub / ai-hub / app / api / routes /
..
README.md add demo code & cors enabled & document the apis 2 months ago
__init__.py refactor the routes api to be more modularized 2 months ago
api.py introduce stt endpoint 2 months ago
documents.py refactor the routes api to be more modularized 2 months ago
general.py refactor the routes api to be more modularized 2 months ago
sessions.py refactor the routes api to be more modularized 2 months ago
stt.py introduce stt endpoint 2 months ago
tts.py refactor the routes api to be more modularized 2 months ago
README.md

Invoking the Text-to-Speech (TTS) API Endpoint

This guide explains how a frontend application can interact with the FastAPI /speech endpoint for text-to-speech conversion. The endpoint supports both non-streaming and streaming audio responses.


1. Endpoint Details

  • HTTP Method: POST
  • Path: /speech
  • Purpose: Convert a given text string into audio.

2. Request Structure

2.1 Request Body

The POST request must include a JSON object matching the SpeechRequest schema.

Field Type Description Example
text string Text to be converted to speech "Hello, this is a test message."

Example JSON body:

{
  "text": "The quick brown fox jumps over the lazy dog."
}

2.2 Query Parameter

Parameter Type Default Description
stream boolean false If true, returns a continuous audio stream. If false, returns the full audio file.

Example URLs:

  • Non-streaming (Default):

    http://[your-api-server]/speech
  • Streaming:

    http://[your-api-server]/speech?stream=true

3. Frontend Implementation (JavaScript)

Below are two implementations using the fetch API.


Example 1: Non-Streaming Response

Downloads the complete WAV file before playing. Suitable for short messages.

// Generate and play non-streaming audio
async function getSpeechAudio(text) {
  const url = 'http://[your-api-server]/speech'; // Replace with your API URL
  
  try {
    const response = await fetch(url, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ text })
    });

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const audioBlob = await response.blob();
    const audioUrl = URL.createObjectURL(audioBlob);

    const audio = new Audio(audioUrl);
    audio.play();

    console.log("Audio file received and is now playing.");
  } catch (error) {
    console.error("Failed to generate speech:", error);
  }
}

// Example:
// getSpeechAudio("This is an example of a non-streaming response.");

Example 2: Streaming Response

Plays audio as it arrives using the MediaSource API. Ideal for long texts.

// Stream audio and play as it arrives
async function streamSpeechAudio(text) {
  const url = 'http://[your-api-server]/speech?stream=true'; // Replace with your API URL
  
  try {
    const response = await fetch(url, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ text })
    });

    if (!response.ok || !response.body) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const mediaSource = new MediaSource();
    const audio = new Audio();
    audio.src = URL.createObjectURL(mediaSource);

    mediaSource.addEventListener('sourceopen', async () => {
      const sourceBuffer = mediaSource.addSourceBuffer('audio/wav');
      const reader = response.body.getReader();
      
      while (true) {
        const { done, value } = await reader.read();
        if (done) {
          mediaSource.endOfStream();
          break;
        }
        sourceBuffer.appendBuffer(value);
      }
    });

    audio.play();
    console.log("Streaming audio is starting...");
  } catch (error) {
    console.error("Failed to stream speech:", error);
  }
}

// Example:
// streamSpeechAudio("This is an example of a streaming response, which begins playing before the entire audio file is received.");

Invoking the Speech-to-Text (STT) API Endpoint

This document explains how a frontend application can interact with the FastAPI /stt/transcribe endpoint to transcribe an uploaded audio file into text.


1. Endpoint Details

  • HTTP Method: POST
  • Path: /stt/transcribe
  • Purpose: Transcribe an uploaded audio file into text.
  • Content Type: multipart/form-data

2. Request Structure

2.1 Request Body

The POST request must include a multipart/form-data object with a single file field named audio_file.

Field Type Description
audio_file File The audio file to be transcribed

3. Frontend Implementation (JavaScript + HTML)

Below is a complete working example using fetch to send the file and display the transcription result.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>STT API Example</title>
  <style>
    body { font-family: sans-serif; padding: 2rem; background-color: #f4f4f9; }
    .container { max-width: 600px; margin: auto; padding: 2rem; background: white; border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); }
    h1 { text-align: center; color: #333; }
    label { display: block; margin-bottom: 0.5rem; font-weight: bold; }
    input[type="file"] { width: 100%; padding: 0.5rem; margin-bottom: 1rem; border: 1px solid #ccc; border-radius: 4px; }
    button { width: 100%; padding: 0.75rem; font-size: 1rem; color: white; background-color: #007bff; border: none; border-radius: 4px; cursor: pointer; transition: background-color 0.3s; }
    button:hover { background-color: #0056b3; }
    #result { margin-top: 1.5rem; padding: 1rem; background-color: #e9ecef; border-radius: 4px; white-space: pre-wrap; }
    #result p { margin: 0; font-style: italic; color: #555; }
    #loading { display: none; text-align: center; margin-top: 1rem; font-weight: bold; color: #6c757d; }
  </style>
</head>
<body>
  <div class="container">
    <h1>Speech-to-Text (STT) Transcription</h1>
    <label for="audioFile">Select an audio file:</label>
    <input type="file" id="audioFile" accept="audio/*">
    <button id="transcribeButton">Transcribe</button>
    <div id="loading">Transcribing...</div>
    <div id="result">
      <p>Your transcribed text will appear here.</p>
    </div>
  </div>

  <script>
    document.getElementById('transcribeButton').addEventListener('click', async () => {
      const fileInput = document.getElementById('audioFile');
      const resultDiv = document.getElementById('result');
      const loadingDiv = document.getElementById('loading');

      if (fileInput.files.length === 0) {
        resultDiv.innerHTML = '<p style="color:red;">Please select an audio file first.</p>';
        return;
      }

      const audioFile = fileInput.files[0];
      loadingDiv.style.display = 'block';
      resultDiv.innerHTML = '';

      const url = 'http://[your-api-server]/stt/transcribe'; // Replace with your API URL

      const formData = new FormData();
      formData.append('audio_file', audioFile);

      try {
        const response = await fetch(url, {
          method: 'POST',
          body: formData
        });

        if (!response.ok) {
          const errorData = await response.json();
          throw new Error(`HTTP error! Status: ${response.status}. Detail: ${errorData.detail}`);
        }

        const result = await response.json();
        resultDiv.innerHTML = `<h3>Transcription Result:</h3><p>${result.transcript}</p>`;
        console.log("Transcription successful:", result.transcript);
      } catch (error) {
        resultDiv.innerHTML = `<h3 style="color:red;">Error:</h3><p>${error.message}</p>`;
        console.error("Transcription failed:", error);
      } finally {
        loadingDiv.style.display = 'none';
      }
    });
  </script>
</body>
</html>

Here’s your Chat Sessions API documentation reformatted for clarity, structure, and consistency:


Invoking the Chat Sessions API Endpoint

This document describes how a frontend application can interact with the FastAPI /sessions endpoints. These endpoints allow you to:

  • Create new chat sessions
  • Send messages within a session
  • Retrieve chat history

1. Endpoint Details

HTTP Method Path Purpose Request Type
POST /sessions/ Creates a new chat session application/json
POST /sessions/{session_id}/chat Sends a message and receives a response in a specific session application/json
GET /sessions/{session_id}/messages Retrieves the message history for a given session N/A

2. Request & Response Structures

2.1 Create a New Chat Session

POST /sessions/

Request Body:

Field Type Description
user_id string ID of the user creating the session
model string Model to use for the session

Example Request:

{
  "user_id": "user-1234",
  "model": "gemini"
}

Response Body:

Field Type Description
id integer Session ID
user_id string User ID
created_at string Session creation timestamp
model string Model used

2.2 Send a Message in a Session

POST /sessions/{session_id}/chat

Path Parameter:

Name Type Description
session_id integer Unique session ID

Request Body:

Field Type Description
prompt string User message
model string Model for this message (can override session default)
load_faiss_retriever boolean Whether to use FAISS retriever

Example Request:

{
  "prompt": "What is the capital of France?",
  "model": "gemini",
  "load_faiss_retriever": false
}

Response Body:

Field Type Description
answer string Model's answer
model_used string Model used for the response

2.3 Get Session Chat History

GET /sessions/{session_id}/messages

Path Parameter:

Name Type Description
session_id integer Unique session ID

Response Body:

Field Type Description
session_id integer Session ID
messages array List of message objects (role, content, timestamp)

3. Frontend Implementation (HTML + JavaScript)

Below is a complete example that:

  1. Creates a new chat session
  2. Sends a message in the session
  3. Retrieves the chat history
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Chat Sessions API Example</title>
  <style>
    body { font-family: sans-serif; padding: 2rem; background-color: #f4f4f9; }
    .container { max-width: 800px; margin: auto; padding: 2rem; background: white; border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); }
    h1 { text-align: center; color: #333; }
    h2 { border-bottom: 2px solid #ccc; padding-bottom: 0.5rem; margin-top: 2rem; }
    button { padding: 0.75rem 1.5rem; font-size: 1rem; color: white; background-color: #007bff; border: none; border-radius: 4px; cursor: pointer; transition: background-color 0.3s; margin-top: 1rem; }
    button:hover { background-color: #0056b3; }
    pre { background-color: #e9ecef; padding: 1rem; border-radius: 4px; white-space: pre-wrap; font-family: monospace; }
    .result { margin-top: 1.5rem; }
  </style>
</head>
<body>
  <div class="container">
    <h1>Chat Sessions API Example</h1>
    <p>This page demonstrates creating a session, sending a message, and retrieving the history.</p>
    <button id="runWorkflowButton">Run Full Workflow</button>
    <div class="result">
      <h2>Workflow Log</h2>
      <pre id="output"></pre>
    </div>
  </div>

  <script>
    const API_URL = 'http://[your-api-server]'; // Replace with your API URL
    const outputDiv = document.getElementById('output');

    function log(message) {
      outputDiv.textContent += message + '\n\n';
      outputDiv.scrollTop = outputDiv.scrollHeight;
    }

    document.getElementById('runWorkflowButton').addEventListener('click', async () => {
      outputDiv.textContent = '';
      let sessionId = null;

      log("Starting workflow...");

      // Step 1: Create session
      log("1. Creating session...");
      try {
        const res = await fetch(`${API_URL}/sessions/`, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ user_id: "demo-user-123", model: "gemini-1.5-flash" })
        });
        if (!res.ok) throw new Error(`HTTP error ${res.status}`);
        const session = await res.json();
        sessionId = session.id;
        log(`Session created: ${sessionId}`);
      } catch (err) {
        log(`Error creating session: ${err.message}`);
        return;
      }

      // Step 2: Send message
      log("2. Sending message...");
      try {
        const res = await fetch(`${API_URL}/sessions/${sessionId}/chat`, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ 
            prompt: "What is the primary function of a web browser?",
            model: "gemini",
            load_faiss_retriever: false
          })
        });
        if (!res.ok) throw new Error(`HTTP error ${res.status}`);
        const chatRes = await res.json();
        log(`Answer: ${chatRes.answer}`);
      } catch (err) {
        log(`Error sending message: ${err.message}`);
        return;
      }

      // Step 3: Get history
      log("3. Getting chat history...");
      try {
        const res = await fetch(`${API_URL}/sessions/${sessionId}/messages`);
        if (!res.ok) throw new Error(`HTTP error ${res.status}`);
        const history = await res.json();
        log(`History: ${JSON.stringify(history, null, 2)}`);
      } catch (err) {
        log(`Error getting history: ${err.message}`);
      }

      log("Workflow complete!");
    });
  </script>
</body>
</html>

Invoking the Documents API Endpoint

This guide explains how a frontend application can interact with the FastAPI /documents endpoints. These endpoints allow you to add, list, and delete documents.


Endpoint Summary

HTTP Method Path Purpose Request Type
POST /documents/ Adds a new document. application/json
GET /documents/ Lists all documents. N/A
DELETE /documents/{document_id} Deletes a specific document by ID. N/A

Request & Response Structures

1. Add a New Document

POST /documents/

Request Body (JSON):

  • title (string) – The title of the document.
  • content (string) – The content of the document.

Example Request:

{
  "title": "My First Document",
  "content": "This is the content of my very first document."
}

Response Body:

  • message (string) – Success message.

2. List All Documents

GET /documents/

Request Body: None.

Response Body:

  • documents (array) – List of documents. Each object contains:
    • id (integer)
    • title (string)
    • content (string)
    • created_at (timestamp)

3. Delete a Document

DELETE /documents/{document_id}

Path Parameters:

  • document_id (integer) – Unique ID of the document to be deleted.

Response Body:

  • message (string) – Success message.
  • document_id (integer) – ID of the deleted document.

Frontend Implementation (JavaScript Example)

Below is a complete HTML + JavaScript example showing how to add, list, and delete documents using the API.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documents API Example</title>
    <style>
        body { font-family: sans-serif; padding: 2rem; background-color: #f4f4f9; }
        .container { max-width: 800px; margin: auto; padding: 2rem; background: white; border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); }
        h1 { text-align: center; color: #333; }
        h2 { border-bottom: 2px solid #ccc; padding-bottom: 0.5rem; margin-top: 2rem; }
        form { margin-bottom: 1rem; }
        label { display: block; margin-top: 1rem; margin-bottom: 0.5rem; font-weight: bold; }
        input[type="text"], textarea { width: 100%; padding: 0.5rem; border: 1px solid #ccc; border-radius: 4px; }
        button { padding: 0.75rem 1.5rem; font-size: 1rem; color: white; background-color: #007bff; border: none; border-radius: 4px; cursor: pointer; margin-top: 1rem; }
        button:hover { background-color: #0056b3; }
        .document-item { display: flex; justify-content: space-between; align-items: center; border: 1px solid #ddd; padding: 0.75rem; margin-bottom: 0.5rem; border-radius: 4px; }
        .document-item button { background-color: #dc3545; padding: 0.5rem; font-size: 0.8rem; }
        .document-item button:hover { background-color: #c82333; }
        pre { background-color: #e9ecef; padding: 1rem; border-radius: 4px; white-space: pre-wrap; }
    </style>
</head>
<body>
    <div class="container">
        <h1>Documents API Example</h1>
        
        <h2>Add a New Document</h2>
        <form id="add-doc-form">
            <label for="doc-title">Document Title:</label>
            <input type="text" id="doc-title" required>
            <label for="doc-content">Document Content:</label>
            <textarea id="doc-content" rows="4" required></textarea>
            <button type="submit">Add Document</button>
        </form>

        <h2>Documents List</h2>
        <button id="refresh-docs-button">Refresh Documents</button>
        <div id="documents-list"></div>

        <h2>Log</h2>
        <pre id="log-output"></pre>
    </div>

    <script>
        const API_URL = 'http://[your-api-server]';
        const logOutput = document.getElementById('log-output');
        const documentsListDiv = document.getElementById('documents-list');

        function log(message) {
            logOutput.textContent += message + '\n';
            logOutput.scrollTop = logOutput.scrollHeight;
        }
        
        document.getElementById('add-doc-form').addEventListener('submit', async (e) => {
            e.preventDefault();
            const title = document.getElementById('doc-title').value;
            const content = document.getElementById('doc-content').value;

            log("Adding a new document...");
            try {
                const response = await fetch(`${API_URL}/documents/`, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ title, content })
                });

                if (!response.ok) throw new Error(`HTTP error ${response.status}`);

                const result = await response.json();
                log(`✅ Added document: ${result.message}`);
                e.target.reset();
                getDocuments();
            } catch (error) {
                log(`❌ Error: ${error.message}`);
            }
        });

        async function getDocuments() {
            log("Fetching documents...");
            documentsListDiv.innerHTML = '';
            try {
                const response = await fetch(`${API_URL}/documents/`);
                if (!response.ok) throw new Error(`HTTP error ${response.status}`);
                
                const data = await response.json();
                log(`📄 Found ${data.documents.length} documents.`);

                if (data.documents.length) {
                    data.documents.forEach(doc => {
                        const docItem = document.createElement('div');
                        docItem.className = 'document-item';
                        docItem.innerHTML = `
                            <span><strong>${doc.title}</strong> (ID: ${doc.id})</span>
                            <button onclick="deleteDocument(${doc.id})">Delete</button>
                        `;
                        documentsListDiv.appendChild(docItem);
                    });
                } else {
                    documentsListDiv.innerHTML = '<p>No documents found.</p>';
                }
            } catch (error) {
                log(`❌ Error: ${error.message}`);
            }
        }
        
        async function deleteDocument(id) {
            log(`Deleting document ID: ${id}`);
            try {
                const response = await fetch(`${API_URL}/documents/${id}`, { method: 'DELETE' });
                if (!response.ok) throw new Error(`HTTP error ${response.status}`);
                
                const result = await response.json();
                log(`🗑 Deleted: ${result.message}`);
                getDocuments();
            } catch (error) {
                log(`❌ Error: ${error.message}`);
            }
        }
        
        document.getElementById('refresh-docs-button').addEventListener('click', getDocuments);
        getDocuments();
    </script>
</body>
</html>