diff --git a/.github/workflows/run-javascript-midjourney.yml b/.github/workflows/run-javascript-midjourney.yml new file mode 100644 index 0000000..6e2e499 --- /dev/null +++ b/.github/workflows/run-javascript-midjourney.yml @@ -0,0 +1,49 @@ +name: Run JavaScript Midjourney Example + +on: + workflow_dispatch: + inputs: + prompt: + description: 'Midjourney prompt for image generation' + required: false + default: 'A beautiful sunset over the snow mountains --v 7' + type: string + +jobs: + run-example: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + cache-dependency-path: examples/javascript/package-lock.json + + - name: Install dependencies + working-directory: examples/javascript + run: npm ci + + - name: Create .env file + working-directory: examples/javascript + run: | + echo "LEGNEXT_API_KEY=${{ secrets.LEGNEXT_API_KEY }}" >> .env + echo "LEGNEXT_API_BASE=https://api.legnext.ai/api" >> .env + + - name: Run Midjourney example + working-directory: examples/javascript + run: node midjourney-example.js + env: + PROMPT: ${{ inputs.prompt }} + + - name: Upload execution logs + if: always() + uses: actions/upload-artifact@v4 + with: + name: execution-logs-${{ github.run_number }} + path: examples/javascript/*.log + if-no-files-found: ignore diff --git a/.github/workflows/run-python-midjourney.yml b/.github/workflows/run-python-midjourney.yml new file mode 100644 index 0000000..6500b2d --- /dev/null +++ b/.github/workflows/run-python-midjourney.yml @@ -0,0 +1,49 @@ +name: Run Python Midjourney Example + +on: + workflow_dispatch: + inputs: + prompt: + description: 'Midjourney prompt for image generation' + required: false + default: 'A beautiful sunset over the snow mountains --v 7' + type: string + +jobs: + run-example: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + cache: 'pip' + cache-dependency-path: examples/python/requirements.txt + + - name: Install dependencies + working-directory: examples/python + run: pip install -r requirements.txt + + - name: Create .env file + working-directory: examples/python + run: | + echo "LEGNEXT_API_KEY=${{ secrets.LEGNEXT_API_KEY }}" >> .env + echo "LEGNEXT_API_BASE=https://api.legnext.ai/api" >> .env + + - name: Run Midjourney example + working-directory: examples/python + run: python midjourney_example.py + env: + PROMPT: ${{ inputs.prompt }} + + - name: Upload execution logs + if: always() + uses: actions/upload-artifact@v4 + with: + name: execution-logs-${{ github.run_number }} + path: examples/python/*.log + if-no-files-found: ignore diff --git a/.gitignore b/.gitignore index 13dfa36..a6bd652 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ .env -node_modules/ \ No newline at end of file +node_modules/ +__pycache__/ +*.pyc +*.pyo +*.pyd \ No newline at end of file diff --git a/examples/javascript/.env.example b/examples/javascript/.env.example index 97b284d..d02f485 100644 --- a/examples/javascript/.env.example +++ b/examples/javascript/.env.example @@ -4,4 +4,9 @@ # OpenAI API key for authenticating requests OPENAI_API_KEY=YOUR_TOKEN_HERE -OPENAI_API_BASE=https://api.deep.assistant.run.place/v1 \ No newline at end of file +OPENAI_API_BASE=https://api.deep.assistant.run.place/v1 + +# Legnext API key for Midjourney image generation +# Get your API key from https://legnext.ai/app/api-keys +LEGNEXT_API_KEY=YOUR_LEGNEXT_API_KEY +LEGNEXT_API_BASE=https://api.legnext.ai/api \ No newline at end of file diff --git a/examples/javascript/README.md b/examples/javascript/README.md index bfdd84c..744702e 100644 --- a/examples/javascript/README.md +++ b/examples/javascript/README.md @@ -1,6 +1,11 @@ # JavaScript Example -This example demonstrates how to use the Deep.Assistant API with JavaScript/Node.js and the OpenAI SDK. +This directory contains examples for using different APIs with JavaScript/Node.js. + +## Examples + +1. **Deep.Assistant API** (`example.js`) - OpenAI-compatible API gateway +2. **Midjourney API via Legnext** (`midjourney-example.js`) - Generate images using Midjourney ## Setup @@ -8,11 +13,16 @@ This example demonstrates how to use the Deep.Assistant API with JavaScript/Node ```bash cp .env.example .env ``` - + Then edit `.env` with your API credentials: ```env + # For Deep.Assistant API OPENAI_API_KEY=YOUR_TOKEN_HERE OPENAI_API_BASE=https://api.deep.assistant.run.place/v1 + + # For Legnext Midjourney API + LEGNEXT_API_KEY=YOUR_LEGNEXT_API_KEY + LEGNEXT_API_BASE=https://api.legnext.ai/api ``` 2. Install dependencies: @@ -20,7 +30,9 @@ This example demonstrates how to use the Deep.Assistant API with JavaScript/Node npm install ``` -## Running the Example +## Running the Examples + +### Deep.Assistant API Example ```bash npm start @@ -28,14 +40,30 @@ npm start node example.js ``` -## Code Overview - -The example uses: +This example uses: - `openai` - OpenAI JavaScript SDK - `dotenv` - Environment variable loading from .env file - Standard OpenAI environment variables (`OPENAI_API_KEY`, `OPENAI_BASE_URL`, `OPENAI_API_BASE`) -## API Key +### Midjourney API Example + +```bash +npm run midjourney +# or +node midjourney-example.js +``` + +This example demonstrates: +- Creating an image generation job with a text prompt +- Polling for job completion +- Retrieving the generated image URL + +The example uses: +- `node-fetch` - HTTP client for API requests +- `dotenv` - Environment variable loading from .env file +- Legnext API for unofficial Midjourney access + +## API Keys -Get your API key from the Telegram bot: https://t.me/DeepGPTBot -Use the `/api` command to obtain your key. \ No newline at end of file +- **Deep.Assistant API Key**: Get from the Telegram bot at https://t.me/DeepGPTBot (use `/api` command) +- **Legnext API Key**: Get from https://legnext.ai/app/api-keys \ No newline at end of file diff --git a/examples/javascript/midjourney-example.js b/examples/javascript/midjourney-example.js new file mode 100644 index 0000000..ee09282 --- /dev/null +++ b/examples/javascript/midjourney-example.js @@ -0,0 +1,130 @@ +import dotenv from 'dotenv'; +import fetch from 'node-fetch'; + +// Load environment variables from .env file +dotenv.config(); + +const LEGNEXT_API_KEY = process.env.LEGNEXT_API_KEY || "YOUR_LEGNEXT_API_KEY"; +const LEGNEXT_API_BASE = process.env.LEGNEXT_API_BASE || "https://api.legnext.ai/api"; + +/** + * Generate an image using Midjourney via Legnext API + * @param {string} prompt - Text prompt for image generation + * @returns {Promise} - Job creation response + */ +async function generateImage(prompt) { + const response = await fetch(`${LEGNEXT_API_BASE}/v1/diffusion`, { + method: 'POST', + headers: { + 'x-api-key': LEGNEXT_API_KEY, + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + text: prompt + }) + }); + + if (!response.ok) { + const error = await response.text(); + throw new Error(`Failed to generate image: ${response.status} - ${error}`); + } + + return await response.json(); +} + +/** + * Check the status of a job + * @param {string} jobId - Job ID to check + * @returns {Promise} - Job status response + */ +async function getJobStatus(jobId) { + const response = await fetch(`${LEGNEXT_API_BASE}/v1/job/${jobId}`, { + method: 'GET', + headers: { + 'x-api-key': LEGNEXT_API_KEY + } + }); + + if (!response.ok) { + const error = await response.text(); + throw new Error(`Failed to get job status: ${response.status} - ${error}`); + } + + return await response.json(); +} + +/** + * Wait for job completion by polling + * @param {string} jobId - Job ID to wait for + * @param {number} maxAttempts - Maximum number of polling attempts (default: 60) + * @param {number} intervalMs - Interval between polls in milliseconds (default: 5000) + * @returns {Promise} - Completed job details + */ +async function waitForCompletion(jobId, maxAttempts = 60, intervalMs = 5000) { + for (let i = 0; i < maxAttempts; i++) { + const job = await getJobStatus(jobId); + + console.log(`[${i + 1}/${maxAttempts}] Job status: ${job.status}`); + + if (job.status === 'completed') { + return job; + } else if (job.status === 'failed') { + throw new Error(`Job failed: ${job.error || 'Unknown error'}`); + } + + // Wait before next poll + await new Promise(resolve => setTimeout(resolve, intervalMs)); + } + + throw new Error('Job did not complete within the maximum wait time'); +} + +async function main() { + try { + console.log('Starting Midjourney image generation via Legnext API...\n'); + + const prompt = "A beautiful sunset over the snow mountains --v 7"; + console.log(`Prompt: ${prompt}\n`); + + // Step 1: Generate image + console.log('Step 1: Submitting image generation request...'); + const createResponse = await generateImage(prompt); + const jobId = createResponse.job_id; + console.log(`āœ“ Job created with ID: ${jobId}\n`); + + // Step 2: Wait for completion + console.log('Step 2: Waiting for image generation to complete...'); + const completedJob = await waitForCompletion(jobId); + + // Step 3: Display results + console.log('\nāœ“ Image generation completed!\n'); + console.log('Results:'); + console.log(`- Job ID: ${completedJob.job_id}`); + console.log(`- Status: ${completedJob.status}`); + console.log(`- Model: ${completedJob.model}`); + + if (completedJob.output && completedJob.output.image_url) { + console.log(`\nGenerated Image URL:`); + console.log(completedJob.output.image_url); + } + + if (completedJob.output && completedJob.output.actions) { + console.log(`\nAvailable Actions:`); + completedJob.output.actions.forEach(action => { + console.log(`- ${action}`); + }); + } + + if (completedJob.meta) { + console.log(`\nMetadata:`); + console.log(`- Created: ${completedJob.meta.created_at}`); + console.log(`- Completed: ${completedJob.meta.completed_at}`); + } + + } catch (error) { + console.error('Error:', error.message); + process.exit(1); + } +} + +main(); diff --git a/examples/javascript/package.json b/examples/javascript/package.json index 33e312f..6bc4bd3 100644 --- a/examples/javascript/package.json +++ b/examples/javascript/package.json @@ -6,11 +6,13 @@ "main": "example.js", "scripts": { "test": "node example.js", - "start": "node example.js" + "start": "node example.js", + "midjourney": "node midjourney-example.js" }, "dependencies": { "openai": "^4.0.0", - "dotenv": "^16.0.0" + "dotenv": "^16.0.0", + "node-fetch": "^3.3.0" }, "keywords": ["openai", "api", "testing"], "author": "Deep.Assistant", diff --git a/examples/python/.env.example b/examples/python/.env.example index 97b284d..d02f485 100644 --- a/examples/python/.env.example +++ b/examples/python/.env.example @@ -4,4 +4,9 @@ # OpenAI API key for authenticating requests OPENAI_API_KEY=YOUR_TOKEN_HERE -OPENAI_API_BASE=https://api.deep.assistant.run.place/v1 \ No newline at end of file +OPENAI_API_BASE=https://api.deep.assistant.run.place/v1 + +# Legnext API key for Midjourney image generation +# Get your API key from https://legnext.ai/app/api-keys +LEGNEXT_API_KEY=YOUR_LEGNEXT_API_KEY +LEGNEXT_API_BASE=https://api.legnext.ai/api \ No newline at end of file diff --git a/examples/python/README.md b/examples/python/README.md index 1a33141..e587139 100644 --- a/examples/python/README.md +++ b/examples/python/README.md @@ -1,6 +1,11 @@ # Python Example -This example demonstrates how to use the Deep.Assistant API with Python and the OpenAI SDK. +This directory contains examples for using different APIs with Python. + +## Examples + +1. **Deep.Assistant API** (`example.py`) - OpenAI-compatible API gateway +2. **Midjourney API via Legnext** (`midjourney_example.py`) - Generate images using Midjourney ## Setup @@ -8,11 +13,16 @@ This example demonstrates how to use the Deep.Assistant API with Python and the ```bash cp .env.example .env ``` - + Then edit `.env` with your API credentials: ```env + # For Deep.Assistant API OPENAI_API_KEY=YOUR_TOKEN_HERE OPENAI_API_BASE=https://api.deep.assistant.run.place/v1 + + # For Legnext Midjourney API + LEGNEXT_API_KEY=YOUR_LEGNEXT_API_KEY + LEGNEXT_API_BASE=https://api.legnext.ai/api ``` 2. Install dependencies: @@ -20,7 +30,9 @@ This example demonstrates how to use the Deep.Assistant API with Python and the pip install -r requirements.txt ``` -## Running the Example +## Running the Examples + +### Deep.Assistant API Example ```bash python example.py @@ -28,14 +40,30 @@ python example.py python3 example.py ``` -## Code Overview - -The example uses: +This example uses: - `openai` - OpenAI Python SDK - `python-dotenv` - Environment variable loading from .env file - Standard OpenAI environment variables (`OPENAI_API_KEY`, `OPENAI_BASE_URL`, `OPENAI_API_BASE`) -## API Key +### Midjourney API Example + +```bash +python midjourney_example.py +# or +python3 midjourney_example.py +``` + +This example demonstrates: +- Creating an image generation job with a text prompt +- Polling for job completion +- Retrieving the generated image URL + +The example uses: +- `requests` - HTTP client for API requests +- `python-dotenv` - Environment variable loading from .env file +- Legnext API for unofficial Midjourney access + +## API Keys -Get your API key from the Telegram bot: https://t.me/DeepGPTBot -Use the `/api` command to obtain your key. \ No newline at end of file +- **Deep.Assistant API Key**: Get from the Telegram bot at https://t.me/DeepGPTBot (use `/api` command) +- **Legnext API Key**: Get from https://legnext.ai/app/api-keys \ No newline at end of file diff --git a/examples/python/midjourney_example.py b/examples/python/midjourney_example.py new file mode 100644 index 0000000..240b8e1 --- /dev/null +++ b/examples/python/midjourney_example.py @@ -0,0 +1,136 @@ +import os +import time +import requests +from dotenv import load_dotenv + +# Load environment variables from .env file +load_dotenv() + +LEGNEXT_API_KEY = os.getenv("LEGNEXT_API_KEY", "YOUR_LEGNEXT_API_KEY") +LEGNEXT_API_BASE = os.getenv("LEGNEXT_API_BASE", "https://api.legnext.ai/api") + + +def generate_image(prompt: str) -> dict: + """ + Generate an image using Midjourney via Legnext API + + Args: + prompt: Text prompt for image generation + + Returns: + Job creation response dictionary + """ + url = f"{LEGNEXT_API_BASE}/v1/diffusion" + headers = { + "x-api-key": LEGNEXT_API_KEY, + "Content-Type": "application/json" + } + data = { + "text": prompt + } + + response = requests.post(url, headers=headers, json=data) + + if not response.ok: + raise Exception(f"Failed to generate image: {response.status_code} - {response.text}") + + return response.json() + + +def get_job_status(job_id: str) -> dict: + """ + Check the status of a job + + Args: + job_id: Job ID to check + + Returns: + Job status response dictionary + """ + url = f"{LEGNEXT_API_BASE}/v1/job/{job_id}" + headers = { + "x-api-key": LEGNEXT_API_KEY + } + + response = requests.get(url, headers=headers) + + if not response.ok: + raise Exception(f"Failed to get job status: {response.status_code} - {response.text}") + + return response.json() + + +def wait_for_completion(job_id: str, max_attempts: int = 60, interval_seconds: int = 5) -> dict: + """ + Wait for job completion by polling + + Args: + job_id: Job ID to wait for + max_attempts: Maximum number of polling attempts (default: 60) + interval_seconds: Interval between polls in seconds (default: 5) + + Returns: + Completed job details dictionary + """ + for i in range(max_attempts): + job = get_job_status(job_id) + + print(f"[{i + 1}/{max_attempts}] Job status: {job['status']}") + + if job["status"] == "completed": + return job + elif job["status"] == "failed": + error = job.get("error", "Unknown error") + raise Exception(f"Job failed: {error}") + + # Wait before next poll + time.sleep(interval_seconds) + + raise Exception("Job did not complete within the maximum wait time") + + +def main(): + try: + print("Starting Midjourney image generation via Legnext API...\n") + + prompt = "A beautiful sunset over the snow mountains --v 7" + print(f"Prompt: {prompt}\n") + + # Step 1: Generate image + print("Step 1: Submitting image generation request...") + create_response = generate_image(prompt) + job_id = create_response["job_id"] + print(f"āœ“ Job created with ID: {job_id}\n") + + # Step 2: Wait for completion + print("Step 2: Waiting for image generation to complete...") + completed_job = wait_for_completion(job_id) + + # Step 3: Display results + print("\nāœ“ Image generation completed!\n") + print("Results:") + print(f"- Job ID: {completed_job['job_id']}") + print(f"- Status: {completed_job['status']}") + print(f"- Model: {completed_job['model']}") + + if completed_job.get("output") and completed_job["output"].get("image_url"): + print(f"\nGenerated Image URL:") + print(completed_job["output"]["image_url"]) + + if completed_job.get("output") and completed_job["output"].get("actions"): + print(f"\nAvailable Actions:") + for action in completed_job["output"]["actions"]: + print(f"- {action}") + + if completed_job.get("meta"): + print(f"\nMetadata:") + print(f"- Created: {completed_job['meta'].get('created_at')}") + print(f"- Completed: {completed_job['meta'].get('completed_at')}") + + except Exception as error: + print(f"Error: {error}") + exit(1) + + +if __name__ == "__main__": + main() diff --git a/examples/python/requirements.txt b/examples/python/requirements.txt index a881125..f97a888 100644 --- a/examples/python/requirements.txt +++ b/examples/python/requirements.txt @@ -1,2 +1,3 @@ openai>=1.0.0 -python-dotenv>=1.0.0 \ No newline at end of file +python-dotenv>=1.0.0 +requests>=2.31.0 \ No newline at end of file