Initial commit
This commit is contained in:
12
.claude-plugin/plugin.json
Normal file
12
.claude-plugin/plugin.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "raygent-skills",
|
||||
"description": "Ray's Skills for AI Agents, starting with Claude Skills.",
|
||||
"version": "0.0.0-2025.11.28",
|
||||
"author": {
|
||||
"name": "Raymond Weitekamp",
|
||||
"email": "zhongweili@tubi.tv"
|
||||
},
|
||||
"skills": [
|
||||
"./skills/openrouter"
|
||||
]
|
||||
}
|
||||
3
README.md
Normal file
3
README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# raygent-skills
|
||||
|
||||
Ray's Skills for AI Agents, starting with Claude Skills.
|
||||
52
plugin.lock.json
Normal file
52
plugin.lock.json
Normal file
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"$schema": "internal://schemas/plugin.lock.v1.json",
|
||||
"pluginId": "gh:rawwerks/raygent-skills:raygent-skills",
|
||||
"normalized": {
|
||||
"repo": null,
|
||||
"ref": "refs/tags/v20251128.0",
|
||||
"commit": "2289c4e966e0a025a5de7838e98685980cb40802",
|
||||
"treeHash": "e3b90613e06ec3ecbf05d89dfb9e55312826cd0552ff1c60573543f774ad24b4",
|
||||
"generatedAt": "2025-11-28T10:27:55.740960Z",
|
||||
"toolVersion": "publish_plugins.py@0.2.0"
|
||||
},
|
||||
"origin": {
|
||||
"remote": "git@github.com:zhongweili/42plugin-data.git",
|
||||
"branch": "master",
|
||||
"commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390",
|
||||
"repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data"
|
||||
},
|
||||
"manifest": {
|
||||
"name": "raygent-skills",
|
||||
"description": "Ray's Skills for AI Agents, starting with Claude Skills."
|
||||
},
|
||||
"content": {
|
||||
"files": [
|
||||
{
|
||||
"path": "README.md",
|
||||
"sha256": "9c26cd7b1ca5bbae1b4177d772266175feb1aaafb6128bb3f2effdb187a7e9e5"
|
||||
},
|
||||
{
|
||||
"path": ".claude-plugin/plugin.json",
|
||||
"sha256": "621bf115bd2e435e55c5fb51d06dc8256a77abb171714cc3882f3f9c47c77365"
|
||||
},
|
||||
{
|
||||
"path": "skills/openrouter/SKILL.md",
|
||||
"sha256": "6c50824c5016f418ba1aab7b2a7faf5aceff32eedcf70bb75a244b8cc8c68f20"
|
||||
},
|
||||
{
|
||||
"path": "skills/openrouter/references/models_and_features.md",
|
||||
"sha256": "542fa5af38e850a84631f215346c9ffbe236a3187ba3cfee506bf05359218927"
|
||||
},
|
||||
{
|
||||
"path": "skills/openrouter/scripts/call_openrouter.sh",
|
||||
"sha256": "e54742bfda77001541322294ace3cac6494f5547b41bf86b8f1864047b48beba"
|
||||
}
|
||||
],
|
||||
"dirSha256": "e3b90613e06ec3ecbf05d89dfb9e55312826cd0552ff1c60573543f774ad24b4"
|
||||
},
|
||||
"security": {
|
||||
"scannedAt": null,
|
||||
"scannerVersion": null,
|
||||
"flags": []
|
||||
}
|
||||
}
|
||||
277
skills/openrouter/SKILL.md
Normal file
277
skills/openrouter/SKILL.md
Normal file
@@ -0,0 +1,277 @@
|
||||
---
|
||||
name: openrouter
|
||||
description: Use this skill when the user wants to call different LLM models through OpenRouter's unified API, compare model responses, track costs and response times, or find the best model for a task. Triggers include requests to test models, benchmark performance, use specific providers (OpenAI, Anthropic, Google, etc.), or optimize for speed/cost.
|
||||
---
|
||||
|
||||
# OpenRouter
|
||||
|
||||
## Overview
|
||||
|
||||
OpenRouter provides a unified API to access hundreds of LLM models from different providers (OpenAI, Anthropic, Google, Meta, and more) with automatic routing, cost tracking, and performance monitoring. Use this skill to make API calls to any OpenRouter model, compare responses across models, track costs and latency, and optimize model selection.
|
||||
|
||||
## Quick Start
|
||||
|
||||
To call an OpenRouter model:
|
||||
|
||||
1. Set `OPENROUTER_API_KEY` in your environment
|
||||
2. Use the `scripts/call_openrouter.sh` script with `--model` and `--prompt` flags
|
||||
3. Add `--json` flag for structured output
|
||||
|
||||
The script returns:
|
||||
- **Response time** in seconds (wall-clock time)
|
||||
- **Cost** in dollars (OpenRouter pricing)
|
||||
- **Full response content**
|
||||
- **Token counts** (prompt, completion, total)
|
||||
|
||||
## Making API Calls
|
||||
|
||||
### Basic Usage
|
||||
|
||||
The `scripts/call_openrouter.sh` script provides a flexible CLI interface:
|
||||
|
||||
```bash
|
||||
# Basic call
|
||||
bash scripts/call_openrouter.sh \
|
||||
--model "anthropic/claude-3.5-sonnet" \
|
||||
--prompt "Explain quantum computing" \
|
||||
--json
|
||||
|
||||
# With optional parameters
|
||||
bash scripts/call_openrouter.sh \
|
||||
--model "openai/gpt-4o:nitro" \
|
||||
--prompt "Write a haiku" \
|
||||
--max-tokens 100 \
|
||||
--temperature 0.7 \
|
||||
--json
|
||||
```
|
||||
|
||||
### Command-Line Arguments
|
||||
|
||||
- `--model` (required): Model ID (e.g., "anthropic/claude-3.5-sonnet")
|
||||
- `--prompt` (required): User prompt/question
|
||||
- `--system`: Optional system message
|
||||
- `--max-tokens`: Maximum tokens to generate
|
||||
- `--temperature`: Temperature (0.0-2.0)
|
||||
- `--json`: Output as JSON (default: human-readable)
|
||||
|
||||
### Environment Variables
|
||||
|
||||
- `OPENROUTER_API_KEY` (required): Your API key
|
||||
- `OPENROUTER_REFERER` (optional): HTTP referer for tracking (default: http://localhost)
|
||||
- `OPENROUTER_TITLE` (optional): Title for tracking (default: Local Test)
|
||||
- `MODEL` (optional): Override the default model
|
||||
|
||||
### Reading the Output
|
||||
|
||||
The script outputs:
|
||||
1. Response time in seconds (measured client-side)
|
||||
2. Complete JSON response with:
|
||||
- `choices[0].message.content`: The model's response
|
||||
- `usage.prompt_tokens`: Input token count
|
||||
- `usage.completion_tokens`: Output token count
|
||||
- `usage.total_tokens`: Total tokens used
|
||||
|
||||
### Cost Calculation
|
||||
|
||||
To calculate costs:
|
||||
1. Get the model's pricing from the models list (see references)
|
||||
2. Calculate: `(prompt_tokens × prompt_price) + (completion_tokens × completion_price)`
|
||||
|
||||
Example: If a model costs $0.0000025/token for prompts and $0.000002/token for completions, and uses 14 prompt + 277 completion tokens:
|
||||
- Cost = (14 × 0.0000025) + (277 × 0.000002) = $0.000035 + $0.000554 = $0.000589
|
||||
|
||||
## Model Selection
|
||||
|
||||
### Finding Models
|
||||
|
||||
Retrieve the full models list with pricing and capabilities:
|
||||
|
||||
```bash
|
||||
curl https://openrouter.ai/api/v1/models -H "Authorization: Bearer $OPENROUTER_API_KEY" > models.json
|
||||
```
|
||||
|
||||
The list is sorted by creation date (newest first), serving as a proxy for quality.
|
||||
|
||||
**Important**: The models list can be very large. Consider saving to a file and using grep/jq to filter by:
|
||||
- Price range
|
||||
- Context length
|
||||
- Specific providers
|
||||
- Capabilities (vision, function calling, etc.)
|
||||
|
||||
### Model Naming Format
|
||||
|
||||
OpenRouter uses `provider/model-name`:
|
||||
- `anthropic/claude-3.5-sonnet`
|
||||
- `openai/gpt-4o`
|
||||
- `google/gemini-pro-1.5`
|
||||
- `meta-llama/llama-3.1-405b-instruct`
|
||||
|
||||
### Speed and Feature Modifiers
|
||||
|
||||
**`:nitro`** - Use the fastest available provider for a model
|
||||
```
|
||||
anthropic/claude-3.5-sonnet:nitro
|
||||
```
|
||||
|
||||
**`:online`** - Enable web search capabilities
|
||||
```
|
||||
openai/gpt-4o:online
|
||||
```
|
||||
|
||||
**Combine modifiers:**
|
||||
```
|
||||
anthropic/claude-3.5-sonnet:nitro:online
|
||||
```
|
||||
|
||||
## Common Use Cases
|
||||
|
||||
### Testing a Specific Model
|
||||
|
||||
Edit the script's `PAYLOAD` to use the desired model and messages:
|
||||
|
||||
```bash
|
||||
{
|
||||
"model": "anthropic/claude-3.5-sonnet",
|
||||
"messages": [
|
||||
{"role": "user", "content": "Explain quantum computing in simple terms"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Comparing Models
|
||||
|
||||
Run the script multiple times with different models and compare:
|
||||
- Response quality
|
||||
- Response time
|
||||
- Token usage and cost
|
||||
|
||||
### Finding the Cheapest/Fastest Model
|
||||
|
||||
1. Fetch the models list and save to file
|
||||
2. Use jq or grep to filter by criteria
|
||||
3. Test top candidates with the script
|
||||
4. Compare performance vs. cost trade-offs
|
||||
|
||||
For speed: Try models with `:nitro` suffix
|
||||
For cost: Filter models.json by lowest pricing values
|
||||
|
||||
## Accessing Provider Information (Non-API)
|
||||
|
||||
### Opening Provider Pages with Query Parameters
|
||||
|
||||
While the OpenRouter API provides model information, **provider-specific details** like throughput, latency, and availability are only accessible via the web interface. You can programmatically open these pages with sorting parameters.
|
||||
|
||||
#### URL Structure
|
||||
|
||||
```
|
||||
https://openrouter.ai/<model-slug>/providers?sort=<sorting-option>
|
||||
```
|
||||
|
||||
**Available Sorting Options:**
|
||||
- `throughput` - Sort by provider throughput (tokens/sec)
|
||||
- `price` - Sort by cost
|
||||
- `latency` - Sort by response latency
|
||||
|
||||
#### Example: Opening Provider Page Sorted by Throughput
|
||||
|
||||
For the model `moonshotai/kimi-k2-0905`:
|
||||
|
||||
```
|
||||
https://openrouter.ai/moonshotai/kimi-k2-0905/providers?sort=throughput
|
||||
```
|
||||
|
||||
#### Use Case: Finding the Fastest Provider
|
||||
|
||||
When you need to identify which provider offers the best throughput for a specific model:
|
||||
|
||||
1. Extract the model slug from the model ID (e.g., `openai/gpt-4o` → `openai/gpt-4o`)
|
||||
2. Construct the URL: `https://openrouter.ai/<model-slug>/providers?sort=throughput`
|
||||
3. Open the URL in a browser or use web automation tools
|
||||
4. The page will display providers sorted by throughput (highest first)
|
||||
|
||||
**Note**: This information is **not available through the API** and requires web interface access. The `:nitro` modifier automatically routes to the fastest provider, but if you need to see provider-specific metrics, use the web interface with query parameters.
|
||||
|
||||
#### Workflow for Agent Tools
|
||||
|
||||
If you have browser automation capabilities:
|
||||
- Use `mcp__chrome-devtools__new_page` or similar to open the provider page
|
||||
- The `?sort=throughput` parameter ensures the page loads pre-sorted
|
||||
- Extract provider metrics from the rendered page
|
||||
|
||||
### Accessing Model Rankings by Category
|
||||
|
||||
OpenRouter provides model rankings filtered by specific use cases and categories. These rankings show which models perform best for different tasks based on user ratings and token usage.
|
||||
|
||||
#### URL Structure
|
||||
|
||||
```
|
||||
https://openrouter.ai/rankings?category=<category-value>#categories
|
||||
```
|
||||
|
||||
#### Available Categories
|
||||
|
||||
| Category Display Name | Query Parameter Value | Example URL |
|
||||
|----------------------|----------------------|-------------|
|
||||
| Programming | `programming` | `https://openrouter.ai/rankings?category=programming#categories` |
|
||||
| Roleplay | `roleplay` | `https://openrouter.ai/rankings?category=roleplay#categories` |
|
||||
| Marketing | `marketing` | `https://openrouter.ai/rankings?category=marketing#categories` |
|
||||
| Marketing/Seo | `marketing/seo` | `https://openrouter.ai/rankings?category=marketing/seo#categories` |
|
||||
| Technology | `technology` | `https://openrouter.ai/rankings?category=technology#categories` |
|
||||
| Science | `science` | `https://openrouter.ai/rankings?category=science#categories` |
|
||||
| Translation | `translation` | `https://openrouter.ai/rankings?category=translation#categories` |
|
||||
| Legal | `legal` | `https://openrouter.ai/rankings?category=legal#categories` |
|
||||
| Finance | `finance` | `https://openrouter.ai/rankings?category=finance#categories` |
|
||||
| Health | `health` | `https://openrouter.ai/rankings?category=health#categories` |
|
||||
| Trivia | `trivia` | `https://openrouter.ai/rankings?category=trivia#categories` |
|
||||
| Academia | `academia` | `https://openrouter.ai/rankings?category=academia#categories` |
|
||||
|
||||
#### Usage Notes
|
||||
|
||||
- Most categories use lowercase versions of their names (e.g., `programming`, `science`)
|
||||
- The **Marketing/Seo** category uses `marketing/seo` with a slash
|
||||
- The `#categories` anchor is optional but helps navigate to the categories section
|
||||
- Rankings are **not available through the API** and require web interface access
|
||||
- Each category shows models ranked by performance for that specific use case
|
||||
|
||||
#### Use Case: Finding the Best Model for a Specific Task
|
||||
|
||||
When you need to identify top-performing models for a particular domain:
|
||||
|
||||
1. Select the appropriate category from the table above
|
||||
2. Construct the URL: `https://openrouter.ai/rankings?category=<value>#categories`
|
||||
3. Open the URL in a browser or use web automation tools
|
||||
4. The page displays models ranked by performance for that category
|
||||
|
||||
Example for programming tasks:
|
||||
```
|
||||
https://openrouter.ai/rankings?category=programming#categories
|
||||
```
|
||||
|
||||
#### Workflow for Agent Tools
|
||||
|
||||
If you have browser automation capabilities:
|
||||
- Use `mcp__chrome-devtools__new_page` to open the rankings page
|
||||
- The `?category=<value>` parameter loads the page with the selected category
|
||||
- Verify the category dropdown shows the expected category name
|
||||
- Extract model rankings and performance data from the rendered page
|
||||
|
||||
## Resources
|
||||
|
||||
### scripts/call_openrouter.sh
|
||||
|
||||
Bash script that makes an API call to OpenRouter and returns timing, cost, and full response. Uses curl and jq for simple, dependency-free execution.
|
||||
|
||||
**Requirements**: `jq` (for JSON parsing)
|
||||
|
||||
**Usage**:
|
||||
```bash
|
||||
bash call_openrouter.sh --model "anthropic/claude-3.5-sonnet" --prompt "Your question" --json
|
||||
```
|
||||
|
||||
### references/models_and_features.md
|
||||
|
||||
Detailed reference on:
|
||||
- How to fetch and filter the models list
|
||||
- Model naming conventions
|
||||
- Speed (`:nitro`) and web search (`:online`) modifiers
|
||||
- Cost calculation from usage data
|
||||
61
skills/openrouter/references/models_and_features.md
Normal file
61
skills/openrouter/references/models_and_features.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# OpenRouter Models and Features
|
||||
|
||||
## Getting the Models List
|
||||
|
||||
To get the full list of available models with pricing and capabilities:
|
||||
|
||||
```bash
|
||||
curl https://openrouter.ai/api/v1/models -H "Authorization: Bearer $OPENROUTER_API_KEY"
|
||||
```
|
||||
|
||||
The response includes:
|
||||
- Model ID and name
|
||||
- Pricing (prompt/completion tokens)
|
||||
- Context length
|
||||
- Supported parameters
|
||||
- Architecture details
|
||||
|
||||
**Note**: This list can be very large (thousands of tokens). The models are sorted by creation date (newest first), which serves as a decent proxy for quality given AI's rapid pace.
|
||||
|
||||
**Tip**: Save the full JSON to a file and use grep/jq to filter by price, context length, or capabilities rather than loading everything into context.
|
||||
|
||||
## Model Selection Shortcuts
|
||||
|
||||
### Speed Optimization: `:nitro`
|
||||
Append `:nitro` to any model ID to use the fastest available provider for that model.
|
||||
|
||||
Example: `anthropic/claude-3.5-sonnet:nitro`
|
||||
|
||||
### Web Search: `:online`
|
||||
Append `:online` to any model ID to enable web search capabilities.
|
||||
|
||||
Example: `openai/gpt-4o:online`
|
||||
|
||||
### Combining Modifiers
|
||||
You can combine modifiers:
|
||||
|
||||
Example: `anthropic/claude-3.5-sonnet:nitro:online`
|
||||
|
||||
## Common Model Format
|
||||
|
||||
OpenRouter uses the format `provider/model-name`:
|
||||
- `anthropic/claude-3.5-sonnet`
|
||||
- `openai/gpt-4o`
|
||||
- `google/gemini-pro-1.5`
|
||||
- `meta-llama/llama-3.1-405b-instruct`
|
||||
|
||||
## Cost and Usage Tracking
|
||||
|
||||
The API returns usage data in the response JSON under the `usage` field:
|
||||
```json
|
||||
{
|
||||
"usage": {
|
||||
"prompt_tokens": 14,
|
||||
"completion_tokens": 277,
|
||||
"total_tokens": 291
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Use the model's pricing information to calculate costs:
|
||||
- Cost = (prompt_tokens × prompt_price) + (completion_tokens × completion_price)
|
||||
195
skills/openrouter/scripts/call_openrouter.sh
Executable file
195
skills/openrouter/scripts/call_openrouter.sh
Executable file
@@ -0,0 +1,195 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Check for required API key
|
||||
: "${OPENROUTER_API_KEY:?Set OPENROUTER_API_KEY in your environment}"
|
||||
|
||||
# Parse command-line arguments
|
||||
MODEL=""
|
||||
PROMPT=""
|
||||
SYSTEM_MSG=""
|
||||
MAX_TOKENS=""
|
||||
TEMPERATURE=""
|
||||
JSON_OUTPUT=false
|
||||
|
||||
show_usage() {
|
||||
cat <<EOF
|
||||
Usage: $0 --model MODEL --prompt PROMPT [OPTIONS]
|
||||
|
||||
Required:
|
||||
--model MODEL Model ID (e.g., "anthropic/claude-3.5-sonnet")
|
||||
--prompt PROMPT User prompt/question
|
||||
|
||||
Optional:
|
||||
--system SYSTEM System message
|
||||
--max-tokens N Maximum tokens to generate
|
||||
--temperature N Temperature (0.0-2.0)
|
||||
--json Output as JSON
|
||||
--help Show this help message
|
||||
|
||||
Environment Variables:
|
||||
OPENROUTER_API_KEY Your OpenRouter API key (required)
|
||||
OPENROUTER_REFERER HTTP referer for tracking (default: https://raw.works)
|
||||
OPENROUTER_TITLE Title for tracking (default: RAW.works)
|
||||
|
||||
Examples:
|
||||
$0 --model "openai/gpt-4o-mini" --prompt "What is 2+2?" --json
|
||||
$0 --model "anthropic/claude-3.5-sonnet:nitro" --prompt "Explain quantum computing" --max-tokens 500
|
||||
EOF
|
||||
}
|
||||
|
||||
# Parse arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--model)
|
||||
MODEL="$2"
|
||||
shift 2
|
||||
;;
|
||||
--prompt)
|
||||
PROMPT="$2"
|
||||
shift 2
|
||||
;;
|
||||
--system)
|
||||
SYSTEM_MSG="$2"
|
||||
shift 2
|
||||
;;
|
||||
--max-tokens)
|
||||
MAX_TOKENS="$2"
|
||||
shift 2
|
||||
;;
|
||||
--temperature)
|
||||
TEMPERATURE="$2"
|
||||
shift 2
|
||||
;;
|
||||
--json)
|
||||
JSON_OUTPUT=true
|
||||
shift
|
||||
;;
|
||||
--help)
|
||||
show_usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Error: Unknown option $1" >&2
|
||||
show_usage >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Validate required arguments
|
||||
if [[ -z "$MODEL" ]]; then
|
||||
echo "Error: --model is required" >&2
|
||||
show_usage >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z "$PROMPT" ]]; then
|
||||
echo "Error: --prompt is required" >&2
|
||||
show_usage >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Set defaults
|
||||
REFERER="${OPENROUTER_REFERER:-https://raw.works}"
|
||||
TITLE="${OPENROUTER_TITLE:-RAW.works}"
|
||||
|
||||
# Build messages array
|
||||
MESSAGES="["
|
||||
if [[ -n "$SYSTEM_MSG" ]]; then
|
||||
MESSAGES="${MESSAGES}{\"role\": \"system\", \"content\": $(printf '%s' "$SYSTEM_MSG" | jq -Rs .)},"
|
||||
fi
|
||||
MESSAGES="${MESSAGES}{\"role\": \"user\", \"content\": $(printf '%s' "$PROMPT" | jq -Rs .)}"
|
||||
MESSAGES="${MESSAGES}]"
|
||||
|
||||
# Build request body
|
||||
REQUEST_BODY=$(cat <<EOF
|
||||
{
|
||||
"model": "$MODEL",
|
||||
"messages": $MESSAGES,
|
||||
"extra_body": {
|
||||
"usage": { "include": true }
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
# Add optional parameters
|
||||
if [[ -n "$MAX_TOKENS" ]]; then
|
||||
REQUEST_BODY="${REQUEST_BODY},\"max_tokens\": $MAX_TOKENS"
|
||||
fi
|
||||
|
||||
if [[ -n "$TEMPERATURE" ]]; then
|
||||
REQUEST_BODY="${REQUEST_BODY},\"temperature\": $TEMPERATURE"
|
||||
fi
|
||||
|
||||
REQUEST_BODY="${REQUEST_BODY}}"
|
||||
|
||||
# Make the API call
|
||||
SECONDS=0
|
||||
TMP_RESPONSE=$(mktemp)
|
||||
HTTP_STATUS=$(
|
||||
curl --silent --show-error \
|
||||
--header "Authorization: Bearer ${OPENROUTER_API_KEY}" \
|
||||
--header "Content-Type: application/json" \
|
||||
--header "HTTP-Referer: ${REFERER}" \
|
||||
--header "X-Title: ${TITLE}" \
|
||||
--data "${REQUEST_BODY}" \
|
||||
--output "${TMP_RESPONSE}" \
|
||||
--write-out '%{http_code}' \
|
||||
https://openrouter.ai/api/v1/chat/completions
|
||||
)
|
||||
ELAPSED_SECONDS=$SECONDS
|
||||
|
||||
# Check for errors
|
||||
if [[ "${HTTP_STATUS}" -ne 200 ]]; then
|
||||
echo "Error: Request failed (HTTP ${HTTP_STATUS}) after ${ELAPSED_SECONDS}s" >&2
|
||||
cat "${TMP_RESPONSE}" >&2
|
||||
rm -f "${TMP_RESPONSE}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Parse response
|
||||
RESPONSE=$(cat "${TMP_RESPONSE}")
|
||||
rm -f "${TMP_RESPONSE}"
|
||||
|
||||
# Extract data from response
|
||||
CONTENT=$(echo "$RESPONSE" | jq -r '.choices[0].message.content // empty')
|
||||
PROMPT_TOKENS=$(echo "$RESPONSE" | jq -r '.usage.prompt_tokens // null')
|
||||
COMPLETION_TOKENS=$(echo "$RESPONSE" | jq -r '.usage.completion_tokens // null')
|
||||
TOTAL_TOKENS=$(echo "$RESPONSE" | jq -r '.usage.total_tokens // null')
|
||||
COST=$(echo "$RESPONSE" | jq -r '.usage.cost // null')
|
||||
|
||||
# Output results
|
||||
if [[ "$JSON_OUTPUT" == true ]]; then
|
||||
# JSON output
|
||||
cat <<EOF
|
||||
{
|
||||
"model": "$MODEL",
|
||||
"success": true,
|
||||
"response_time": $ELAPSED_SECONDS,
|
||||
"cost": $COST,
|
||||
"error": null,
|
||||
"content": $(echo "$CONTENT" | jq -Rs .),
|
||||
"usage": {
|
||||
"prompt_tokens": $PROMPT_TOKENS,
|
||||
"completion_tokens": $COMPLETION_TOKENS,
|
||||
"total_tokens": $TOTAL_TOKENS
|
||||
}
|
||||
}
|
||||
EOF
|
||||
else
|
||||
# Human-readable output
|
||||
echo "Model: $MODEL"
|
||||
echo "Response time: ${ELAPSED_SECONDS}s"
|
||||
echo ""
|
||||
echo "--- Response ---"
|
||||
echo "$CONTENT"
|
||||
echo ""
|
||||
echo "--- Usage ---"
|
||||
echo "Prompt tokens: $PROMPT_TOKENS"
|
||||
echo "Completion tokens: $COMPLETION_TOKENS"
|
||||
echo "Total tokens: $TOTAL_TOKENS"
|
||||
if [[ "$COST" != "null" ]]; then
|
||||
echo "Cost: \$$COST"
|
||||
fi
|
||||
fi
|
||||
Reference in New Issue
Block a user