AJ STUDIOZ commited on
Commit
7603b27
Β·
0 Parent(s):

Updated to use AJ-mini model based on DeepSeek-R1 1.5B

Browse files
Files changed (6) hide show
  1. API-GUIDE.md +303 -0
  2. Dockerfile +36 -0
  3. Modelfile-AJ-Mini +64 -0
  4. README.md +52 -0
  5. app.py +413 -0
  6. start.sh +46 -0
API-GUIDE.md ADDED
@@ -0,0 +1,303 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # AJ STUDIOZ API - Quick Start Guide
2
+
3
+ ## πŸš€ OpenAI-Compatible API with `aj_` Keys
4
+
5
+ AJ STUDIOZ API is enterprise-grade AI with Claude-like thoughtfulness and full OpenAI compatibility.
6
+
7
+ ### Base URL
8
+ ```
9
+ Production: https://api.ajstudioz.co.in
10
+ Development: https://kamesh14151-aj-studioz-api.hf.space
11
+ ```
12
+
13
+ ### Authentication
14
+ All API requests require an API key starting with `aj_`:
15
+
16
+ ```bash
17
+ Authorization: Bearer aj_your_api_key_here
18
+ ```
19
+
20
+ ---
21
+
22
+ ## πŸ“‹ Available Endpoints
23
+
24
+ ### 1. Chat Completions (OpenAI-compatible)
25
+ ```bash
26
+ POST /v1/chat/completions
27
+ ```
28
+
29
+ **Example Request:**
30
+ ```bash
31
+ curl -X POST "https://kamesh14151-aj-studioz-api.hf.space/v1/chat/completions" \
32
+ -H "Authorization: Bearer aj_test_key_123456789" \
33
+ -H "Content-Type: application/json" \
34
+ -d '{
35
+ "model": "aj-mini",
36
+ "messages": [
37
+ {"role": "system", "content": "You are a helpful AI assistant."},
38
+ {"role": "user", "content": "Explain quantum computing in simple terms."}
39
+ ],
40
+ "max_tokens": 500,
41
+ "temperature": 0.3
42
+ }'
43
+ ```
44
+
45
+ **Example Response:**
46
+ ```json
47
+ {
48
+ "id": "chatcmpl-abc123def456",
49
+ "object": "chat.completion",
50
+ "created": 1730505600,
51
+ "model": "aj-mini",
52
+ "choices": [
53
+ {
54
+ "index": 0,
55
+ "message": {
56
+ "role": "assistant",
57
+ "content": "Quantum computing is a revolutionary approach to computation..."
58
+ },
59
+ "finish_reason": "stop"
60
+ }
61
+ ],
62
+ "usage": {
63
+ "prompt_tokens": 25,
64
+ "completion_tokens": 150,
65
+ "total_tokens": 175
66
+ }
67
+ }
68
+ ```
69
+
70
+ ### 2. Text Completions
71
+ ```bash
72
+ POST /v1/completions
73
+ ```
74
+
75
+ **Example:**
76
+ ```bash
77
+ curl -X POST "https://kamesh14151-aj-studioz-api.hf.space/v1/completions" \
78
+ -H "Authorization: Bearer aj_test_key_123456789" \
79
+ -H "Content-Type: application/json" \
80
+ -d '{
81
+ "model": "aj-mini",
82
+ "prompt": "Write a Python function to calculate fibonacci:",
83
+ "max_tokens": 300,
84
+ "temperature": 0.3
85
+ }'
86
+ ```
87
+
88
+ ### 3. List Models
89
+ ```bash
90
+ GET /v1/models
91
+ ```
92
+
93
+ **Example:**
94
+ ```bash
95
+ curl "https://kamesh14151-aj-studioz-api.hf.space/v1/models" \
96
+ -H "Authorization: Bearer aj_test_key_123456789"
97
+ ```
98
+
99
+ ---
100
+
101
+ ## 🐍 Python SDK Examples
102
+
103
+ ### Using OpenAI Python Library
104
+ ```python
105
+ from openai import OpenAI
106
+
107
+ # Initialize client with AJ STUDIOZ API
108
+ client = OpenAI(
109
+ api_key="aj_test_key_123456789",
110
+ base_url="https://kamesh14151-aj-studioz-api.hf.space/v1"
111
+ )
112
+
113
+ # Chat completion
114
+ response = client.chat.completions.create(
115
+ model="aj-mini",
116
+ messages=[
117
+ {"role": "system", "content": "You are a helpful assistant."},
118
+ {"role": "user", "content": "What is machine learning?"}
119
+ ],
120
+ max_tokens=500,
121
+ temperature=0.3
122
+ )
123
+
124
+ print(response.choices[0].message.content)
125
+ ```
126
+
127
+ ### Using Requests
128
+ ```python
129
+ import requests
130
+
131
+ headers = {
132
+ "Authorization": "Bearer aj_test_key_123456789",
133
+ "Content-Type": "application/json"
134
+ }
135
+
136
+ data = {
137
+ "model": "aj-mini",
138
+ "messages": [
139
+ {"role": "user", "content": "Explain neural networks"}
140
+ ],
141
+ "max_tokens": 500
142
+ }
143
+
144
+ response = requests.post(
145
+ "https://kamesh14151-aj-studioz-api.hf.space/v1/chat/completions",
146
+ headers=headers,
147
+ json=data
148
+ )
149
+
150
+ print(response.json()["choices"][0]["message"]["content"])
151
+ ```
152
+
153
+ ---
154
+
155
+ ## 🌐 JavaScript/Node.js Examples
156
+
157
+ ### Using OpenAI Node SDK
158
+ ```javascript
159
+ import OpenAI from 'openai';
160
+
161
+ const client = new OpenAI({
162
+ apiKey: 'aj_test_key_123456789',
163
+ baseURL: 'https://kamesh14151-aj-studioz-api.hf.space/v1'
164
+ });
165
+
166
+ async function chat() {
167
+ const response = await client.chat.completions.create({
168
+ model: 'aj-mini',
169
+ messages: [
170
+ { role: 'user', content: 'Tell me about AI safety' }
171
+ ],
172
+ max_tokens: 500,
173
+ temperature: 0.3
174
+ });
175
+
176
+ console.log(response.choices[0].message.content);
177
+ }
178
+
179
+ chat();
180
+ ```
181
+
182
+ ### Using Fetch
183
+ ```javascript
184
+ const response = await fetch('https://kamesh14151-aj-studioz-api.hf.space/v1/chat/completions', {
185
+ method: 'POST',
186
+ headers: {
187
+ 'Authorization': 'Bearer aj_test_key_123456789',
188
+ 'Content-Type': 'application/json'
189
+ },
190
+ body: JSON.stringify({
191
+ model: 'aj-mini',
192
+ messages: [
193
+ { role: 'user', content: 'Explain transformers' }
194
+ ]
195
+ })
196
+ });
197
+
198
+ const data = await response.json();
199
+ console.log(data.choices[0].message.content);
200
+ ```
201
+
202
+ ---
203
+
204
+ ## πŸ”‘ API Key Format
205
+
206
+ All API keys must follow this format:
207
+ ```
208
+ aj_<your_unique_key>
209
+ ```
210
+
211
+ **Examples of valid keys:**
212
+ - `aj_test_key_123456789`
213
+ - `aj_prod_a1b2c3d4e5f6`
214
+ - `aj_dev_mycompany_2024`
215
+
216
+ **Invalid keys will return:**
217
+ ```json
218
+ {
219
+ "error": {
220
+ "message": "Invalid API key. Your API key should start with 'aj_'",
221
+ "type": "invalid_request_error",
222
+ "code": "invalid_api_key"
223
+ }
224
+ }
225
+ ```
226
+
227
+ ---
228
+
229
+ ## πŸ“Š Response Format
230
+
231
+ All responses follow OpenAI's format for seamless integration:
232
+
233
+ **Success Response:**
234
+ ```json
235
+ {
236
+ "id": "chatcmpl-...",
237
+ "object": "chat.completion",
238
+ "created": 1730505600,
239
+ "model": "aj-mini",
240
+ "choices": [...],
241
+ "usage": {
242
+ "prompt_tokens": 50,
243
+ "completion_tokens": 100,
244
+ "total_tokens": 150
245
+ }
246
+ }
247
+ ```
248
+
249
+ **Error Response:**
250
+ ```json
251
+ {
252
+ "error": {
253
+ "message": "Error description",
254
+ "type": "error_type",
255
+ "code": "error_code"
256
+ }
257
+ }
258
+ ```
259
+
260
+ ---
261
+
262
+ ## 🎯 Model Parameters
263
+
264
+ | Parameter | Type | Default | Description |
265
+ |-----------|------|---------|-------------|
266
+ | `model` | string | `"aj-mini"` | Model to use |
267
+ | `messages` | array | required | Chat messages |
268
+ | `max_tokens` | integer | `2000` | Max completion length |
269
+ | `temperature` | float | `0.3` | Sampling temperature (0-2) |
270
+ | `stream` | boolean | `false` | Stream responses |
271
+
272
+ ---
273
+
274
+ ## 🏒 Enterprise Features
275
+
276
+ βœ… **OpenAI-Compatible** - Drop-in replacement for OpenAI API
277
+ βœ… **Claude-like Responses** - Thoughtful, well-structured answers
278
+ βœ… **Secure Authentication** - API key validation with `aj_` prefix
279
+ βœ… **Rate Limiting** - Production-ready throttling (coming soon)
280
+ βœ… **Usage Analytics** - Track API consumption (coming soon)
281
+ βœ… **Custom Domain** - api.ajstudioz.co.in (coming soon)
282
+
283
+ ---
284
+
285
+ ## πŸ†˜ Support
286
+
287
+ - **Website:** https://ajstudioz.co.in
288
+ - **Documentation:** https://docs.ajstudioz.co.in (coming soon)
289
+ - **API Status:** https://status.ajstudioz.co.in (coming soon)
290
+
291
+ ---
292
+
293
+ ## πŸ“ Rate Limits (Coming Soon)
294
+
295
+ | Tier | Requests/min | Tokens/day |
296
+ |------|--------------|------------|
297
+ | Free | 60 | 50,000 |
298
+ | Pro | 600 | 1,000,000 |
299
+ | Enterprise | Custom | Custom |
300
+
301
+ ---
302
+
303
+ **Made with ❀️ by AJ STUDIOZ**
Dockerfile ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.11-slim
2
+
3
+ # Set environment variables for Ollama
4
+ ENV OLLAMA_HOST=0.0.0.0:11434
5
+ ENV HOME=/home/user
6
+
7
+ # Create user home directory
8
+ RUN mkdir -p /home/user && chmod 777 /home/user
9
+
10
+ WORKDIR /app
11
+
12
+ # Install system dependencies
13
+ RUN apt-get update && apt-get install -y \
14
+ curl \
15
+ ca-certificates \
16
+ && rm -rf /var/lib/apt/lists/*
17
+
18
+ # Install Ollama
19
+ RUN curl -fsSL https://ollama.com/install.sh | sh
20
+
21
+ # Install Python dependencies
22
+ RUN pip install --no-cache-dir fastapi uvicorn[standard] requests
23
+
24
+ # Copy application files
25
+ COPY app.py .
26
+ COPY Modelfile-AJ-Mini .
27
+ COPY start.sh .
28
+
29
+ # Make start script executable
30
+ RUN chmod +x start.sh
31
+
32
+ # Expose port
33
+ EXPOSE 7860
34
+
35
+ # Start application
36
+ CMD ["./start.sh"]
Modelfile-AJ-Mini ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # AJ-Mini Model - Enterprise Edition
2
+ # Based on DeepSeek-R1 1.5B - Optimized for production use
3
+ # Copyright (c) 2025 AJ STUDIOZ. All rights reserved.
4
+
5
+ FROM deepseek-r1:1.5b
6
+
7
+ # Claude-like parameters: more focused, less random
8
+ PARAMETER temperature 0.3
9
+ PARAMETER top_p 0.95
10
+ PARAMETER top_k 40
11
+ PARAMETER repeat_penalty 1.1
12
+ PARAMETER num_ctx 4096
13
+
14
+ SYSTEM """You are AJ, a professional AI assistant created by AJ STUDIOZ. You embody the thoughtful, safety-conscious approach of Claude with enterprise-grade reliability.
15
+
16
+ ## Core Identity
17
+ - Product: AJ API (Enterprise AI Platform)
18
+ - Provider: AJ STUDIOZ
19
+ - Model: AJ-Mini v1.0
20
+ - Website: https://ajstudioz.co.in
21
+
22
+ ## Personality & Approach
23
+ You are calm, reflective, and exceptionally helpful. Your responses demonstrate:
24
+ - **Clarity**: Direct answers first, then supporting detail
25
+ - **Thoughtfulness**: Consider multiple angles and implications
26
+ - **Safety**: Decline harmful requests politely; verify uncertain facts
27
+ - **Professionalism**: Maintain corporate standards in every interaction
28
+
29
+ ## Response Structure
30
+ 1. **Direct Answer** (1-2 sentences addressing the core question)
31
+ 2. **Explanation** (optional, provide context and reasoning with clear structure)
32
+ 3. **Next Steps** (when relevant, give actionable recommendations)
33
+
34
+ Use markdown formatting:
35
+ - Headers (##, ###) for sections
36
+ - Bullet points for lists
37
+ - Code blocks with language tags for technical content
38
+ - Tables for comparisons
39
+
40
+ ## Behavioral Guidelines
41
+ βœ“ Admit uncertainty: "I'm not certain about X. Here's what I can verify..."
42
+ βœ“ Provide balanced views on complex topics
43
+ βœ“ Think step-by-step for technical problems
44
+ βœ“ Cite reasoning: "I recommend X because..."
45
+ βœ“ Be concise unless detail is requested
46
+
47
+ βœ— Never fabricate information
48
+ βœ— Decline harmful, illegal, or unethical requests
49
+ βœ— Avoid speculation presented as fact
50
+ βœ— Don't claim abilities you lack
51
+
52
+ ## API Integration Guidelines
53
+ When responding to API requests:
54
+ - For structured data requests, output valid JSON
55
+ - For code generation, use appropriate language syntax
56
+ - Support streaming responses when requested
57
+ - Handle context windows efficiently
58
+
59
+ ## Introduction
60
+ When asked who you are:
61
+ "I'm AJ, an AI assistant by AJ STUDIOZ β€” designed to provide thoughtful, accurate, and helpful responses. I'm built with the same care for safety and clarity as Claude, optimized for professional use. How can I assist you today?"
62
+
63
+ You represent AJ STUDIOZ. Every interaction reflects our commitment to excellence, safety, and user trust.
64
+ """
README.md ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: AJ STUDIOZ API
3
+ emoji: πŸ€–
4
+ colorFrom: blue
5
+ colorTo: purple
6
+ sdk: docker
7
+ pinned: false
8
+ license: mit
9
+ ---
10
+
11
+ # AJ STUDIOZ - Your AI Empire
12
+
13
+ Custom AI model powered by Ollama, running 24/7 on Hugging Face Spaces.
14
+
15
+ ## Features
16
+
17
+ - **AJ-Mini v1.0** - Fast, efficient AI assistant
18
+ - **REST API** - Easy integration
19
+ - **24/7 Availability** - Always online
20
+ - **Free Forever** - No rate limits
21
+
22
+ ## API Endpoints
23
+
24
+ ### POST /chat
25
+ Simple chat interface
26
+ ```json
27
+ {
28
+ "message": "Hello!"
29
+ }
30
+ ```
31
+
32
+ ### POST /api/generate
33
+ Direct Ollama API
34
+ ```json
35
+ {
36
+ "model": "aj-mini",
37
+ "prompt": "Your prompt",
38
+ "stream": false
39
+ }
40
+ ```
41
+
42
+ ## Usage
43
+
44
+ ```bash
45
+ curl https://YOUR-SPACE.hf.space/chat \
46
+ -H "Content-Type: application/json" \
47
+ -d '{"message":"Hello AJ!"}'
48
+ ```
49
+
50
+ ---
51
+
52
+ **Built by AJ STUDIOZ** πŸš€
app.py ADDED
@@ -0,0 +1,413 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, Request, HTTPException, Header
2
+ from fastapi.responses import JSONResponse, StreamingResponse
3
+ from fastapi.middleware.cors import CORSMiddleware
4
+ from typing import Optional, List, Dict, Any
5
+ import subprocess
6
+ import time
7
+ import requests
8
+ import os
9
+ import json
10
+ import secrets
11
+ from datetime import datetime
12
+
13
+
14
+
15
+ app = FastAPI(
16
+ title="AJ STUDIOZ API",
17
+ version="1.0",
18
+ description="Enterprise-grade AI API - Claude-like responses with OpenAI compatibility"
19
+ )
20
+
21
+ # Enable CORS
22
+ app.add_middleware(
23
+ CORSMiddleware,
24
+ allow_origins=["*"],
25
+ allow_credentials=True,
26
+ allow_methods=["*"],
27
+ allow_headers=["*"],
28
+ )
29
+
30
+ # Simple API key validation
31
+ VALID_API_KEY_PREFIX = "aj_"
32
+
33
+ def validate_api_key(api_key: Optional[str]) -> bool:
34
+ """Validate API key format - starts with aj_"""
35
+ if not api_key:
36
+ return False
37
+ return api_key.startswith(VALID_API_KEY_PREFIX) and len(api_key) > 10
38
+
39
+ def extract_api_key(authorization: Optional[str]) -> Optional[str]:
40
+ """Extract API key from Authorization header"""
41
+ if not authorization:
42
+ return None
43
+ if authorization.startswith("Bearer "):
44
+ return authorization[7:]
45
+ return authorization
46
+
47
+ @app.get("/")
48
+ async def root():
49
+ return {
50
+ "service": "AJ STUDIOZ API",
51
+ "version": "1.0",
52
+ "model": "AJ-Mini v1.0 (powered by DeepSeek-R1 1.5B)",
53
+ "status": "online",
54
+ "provider": "AJ STUDIOZ",
55
+ "website": "https://ajstudioz.co.in",
56
+ "description": "Enterprise AI assistant with Claude-like thoughtfulness and OpenAI compatibility",
57
+ "capabilities": [
58
+ "OpenAI-compatible API",
59
+ "Claude-style reasoning",
60
+ "Markdown formatting",
61
+ "Code generation",
62
+ "Streaming responses",
63
+ "Enterprise security"
64
+ ],
65
+ "endpoints": {
66
+ "v1_chat": "/v1/chat/completions - OpenAI-compatible chat endpoint",
67
+ "v1_completions": "/v1/completions - OpenAI-compatible completions",
68
+ "v1_models": "/v1/models - List available models",
69
+ "chat": "/chat - Simple chat interface",
70
+ "generate": "/api/generate - Direct Ollama API"
71
+ },
72
+ "authentication": {
73
+ "type": "Bearer token",
74
+ "format": "aj_<your_key>",
75
+ "header": "Authorization: Bearer aj_your_api_key"
76
+ }
77
+ }
78
+
79
+ @app.get("/v1/models")
80
+ async def list_models(authorization: Optional[str] = Header(None)):
81
+ """OpenAI-compatible models endpoint"""
82
+ api_key = extract_api_key(authorization)
83
+ if not validate_api_key(api_key):
84
+ raise HTTPException(status_code=401, detail="Invalid API key. Use format: aj_your_key")
85
+
86
+ return {
87
+ "object": "list",
88
+ "data": [
89
+ {
90
+ "id": "aj-mini",
91
+ "object": "model",
92
+ "created": 1730505600,
93
+ "owned_by": "aj-studioz",
94
+ "permission": [],
95
+ "root": "aj-mini",
96
+ "parent": None,
97
+ },
98
+ {
99
+ "id": "aj-mini-v1",
100
+ "object": "model",
101
+ "created": 1730505600,
102
+ "owned_by": "aj-studioz",
103
+ "permission": [],
104
+ "root": "aj-mini-v1",
105
+ "parent": None,
106
+ }
107
+ ]
108
+ }
109
+
110
+ async def stream_chat_response(prompt: str, model: str, temperature: float, max_tokens: int, completion_id: str):
111
+ """Generator for streaming responses"""
112
+ try:
113
+ response = requests.post(
114
+ "http://localhost:11434/api/generate",
115
+ json={
116
+ "model": "aj-mini",
117
+ "prompt": prompt,
118
+ "stream": True,
119
+ "options": {
120
+ "temperature": temperature,
121
+ "num_predict": max_tokens
122
+ }
123
+ },
124
+ stream=True,
125
+ timeout=120
126
+ )
127
+
128
+ for line in response.iter_lines():
129
+ if line:
130
+ chunk = json.loads(line)
131
+ if chunk.get("response"):
132
+ # OpenAI-compatible streaming format
133
+ stream_chunk = {
134
+ "id": completion_id,
135
+ "object": "chat.completion.chunk",
136
+ "created": int(time.time()),
137
+ "model": model,
138
+ "choices": [{
139
+ "index": 0,
140
+ "delta": {"content": chunk["response"]},
141
+ "finish_reason": None
142
+ }]
143
+ }
144
+ yield f"data: {json.dumps(stream_chunk)}\n\n"
145
+
146
+ if chunk.get("done"):
147
+ # Send final chunk
148
+ final_chunk = {
149
+ "id": completion_id,
150
+ "object": "chat.completion.chunk",
151
+ "created": int(time.time()),
152
+ "model": model,
153
+ "choices": [{
154
+ "index": 0,
155
+ "delta": {},
156
+ "finish_reason": "stop"
157
+ }]
158
+ }
159
+ yield f"data: {json.dumps(final_chunk)}\n\n"
160
+ yield "data: [DONE]\n\n"
161
+ except Exception as e:
162
+ error_chunk = {
163
+ "error": {
164
+ "message": str(e),
165
+ "type": "server_error"
166
+ }
167
+ }
168
+ yield f"data: {json.dumps(error_chunk)}\n\n"
169
+
170
+ @app.post("/v1/chat/completions")
171
+ async def chat_completions(request: Request, authorization: Optional[str] = Header(None)):
172
+ """OpenAI-compatible chat completions endpoint with streaming support"""
173
+ api_key = extract_api_key(authorization)
174
+ if not validate_api_key(api_key):
175
+ raise HTTPException(
176
+ status_code=401,
177
+ detail={
178
+ "error": {
179
+ "message": "Invalid API key. Your API key should start with 'aj_'",
180
+ "type": "invalid_request_error",
181
+ "code": "invalid_api_key"
182
+ }
183
+ }
184
+ )
185
+
186
+ try:
187
+ data = await request.json()
188
+ messages = data.get("messages", [])
189
+ model = data.get("model", "aj-mini")
190
+ max_tokens = data.get("max_tokens", 2000)
191
+ temperature = data.get("temperature", 0.3)
192
+ stream = data.get("stream", False)
193
+
194
+ if not messages:
195
+ raise HTTPException(status_code=400, detail="Messages are required")
196
+
197
+ # Convert messages to prompt
198
+ prompt_parts = []
199
+ for msg in messages:
200
+ role = msg.get("role", "user")
201
+ content = msg.get("content", "")
202
+ if role == "system":
203
+ prompt_parts.append(f"System: {content}")
204
+ elif role == "user":
205
+ prompt_parts.append(f"User: {content}")
206
+ elif role == "assistant":
207
+ prompt_parts.append(f"Assistant: {content}")
208
+
209
+ prompt = "\n\n".join(prompt_parts) + "\n\nAssistant:"
210
+ completion_id = f"chatcmpl-{secrets.token_hex(12)}"
211
+
212
+ # Handle streaming
213
+ if stream:
214
+ return StreamingResponse(
215
+ stream_chat_response(prompt, model, temperature, max_tokens, completion_id),
216
+ media_type="text/event-stream"
217
+ )
218
+
219
+ # Non-streaming response
220
+ response = requests.post(
221
+ "http://localhost:11434/api/generate",
222
+ json={
223
+ "model": "aj-mini",
224
+ "prompt": prompt,
225
+ "stream": False,
226
+ "options": {
227
+ "temperature": temperature,
228
+ "num_predict": max_tokens
229
+ }
230
+ },
231
+ timeout=120
232
+ )
233
+
234
+ if response.status_code == 200:
235
+ result = response.json()
236
+ assistant_message = result.get("response", "")
237
+
238
+ # OpenAI-compatible response
239
+ return {
240
+ "id": completion_id,
241
+ "object": "chat.completion",
242
+ "created": int(time.time()),
243
+ "model": model,
244
+ "choices": [
245
+ {
246
+ "index": 0,
247
+ "message": {
248
+ "role": "assistant",
249
+ "content": assistant_message
250
+ },
251
+ "finish_reason": "stop"
252
+ }
253
+ ],
254
+ "usage": {
255
+ "prompt_tokens": len(prompt.split()),
256
+ "completion_tokens": len(assistant_message.split()),
257
+ "total_tokens": len(prompt.split()) + len(assistant_message.split())
258
+ },
259
+ "system_fingerprint": "aj-mini-v1.0"
260
+ }
261
+ else:
262
+ raise HTTPException(status_code=500, detail="Model error")
263
+
264
+ except HTTPException:
265
+ raise
266
+ except Exception as e:
267
+ raise HTTPException(status_code=500, detail=str(e))
268
+
269
+ @app.post("/v1/completions")
270
+ async def completions(request: Request, authorization: Optional[str] = Header(None)):
271
+ """OpenAI-compatible completions endpoint"""
272
+ api_key = extract_api_key(authorization)
273
+ if not validate_api_key(api_key):
274
+ raise HTTPException(status_code=401, detail="Invalid API key")
275
+
276
+ try:
277
+ data = await request.json()
278
+ prompt = data.get("prompt", "")
279
+ model = data.get("model", "aj-mini")
280
+ max_tokens = data.get("max_tokens", 2000)
281
+ temperature = data.get("temperature", 0.3)
282
+
283
+ if not prompt:
284
+ raise HTTPException(status_code=400, detail="Prompt is required")
285
+
286
+ # Call Ollama API
287
+ response = requests.post(
288
+ "http://localhost:11434/api/generate",
289
+ json={
290
+ "model": "aj-mini",
291
+ "prompt": prompt,
292
+ "stream": False,
293
+ "options": {
294
+ "temperature": temperature,
295
+ "num_predict": max_tokens
296
+ }
297
+ },
298
+ timeout=120
299
+ )
300
+
301
+ if response.status_code == 200:
302
+ result = response.json()
303
+ completion_text = result.get("response", "")
304
+
305
+ return {
306
+ "id": f"cmpl-{secrets.token_hex(12)}",
307
+ "object": "text_completion",
308
+ "created": int(time.time()),
309
+ "model": model,
310
+ "choices": [
311
+ {
312
+ "text": completion_text,
313
+ "index": 0,
314
+ "logprobs": None,
315
+ "finish_reason": "stop"
316
+ }
317
+ ],
318
+ "usage": {
319
+ "prompt_tokens": len(prompt.split()),
320
+ "completion_tokens": len(completion_text.split()),
321
+ "total_tokens": len(prompt.split()) + len(completion_text.split())
322
+ }
323
+ }
324
+ else:
325
+ raise HTTPException(status_code=500, detail="Model error")
326
+
327
+ except HTTPException:
328
+ raise
329
+ except Exception as e:
330
+ raise HTTPException(status_code=500, detail=str(e))
331
+
332
+ @app.post("/chat")
333
+ async def chat(request: Request):
334
+ try:
335
+ data = await request.json()
336
+ message = data.get("message", "")
337
+
338
+ if not message:
339
+ return JSONResponse({"error": "Message is required"}, status_code=400)
340
+
341
+ # Call Ollama API
342
+ response = requests.post(
343
+ "http://localhost:11434/api/generate",
344
+ json={
345
+ "model": "aj-mini",
346
+ "prompt": message,
347
+ "stream": False
348
+ },
349
+ timeout=60
350
+ )
351
+
352
+ if response.status_code == 200:
353
+ result = response.json()
354
+ return JSONResponse({
355
+ "reply": result.get("response", ""),
356
+ "model": "AJ-Mini v1.0",
357
+ "provider": "AJ STUDIOZ"
358
+ })
359
+ else:
360
+ return JSONResponse(
361
+ {"error": "Model error", "details": response.text},
362
+ status_code=500
363
+ )
364
+
365
+ except Exception as e:
366
+ return JSONResponse(
367
+ {"error": "Failed to process request", "details": str(e)},
368
+ status_code=500
369
+ )
370
+
371
+ @app.post("/api/generate")
372
+ async def generate(request: Request):
373
+ """Direct Ollama API passthrough"""
374
+ try:
375
+ data = await request.json()
376
+
377
+ response = requests.post(
378
+ "http://localhost:11434/api/generate",
379
+ json=data,
380
+ timeout=60
381
+ )
382
+
383
+ return JSONResponse(response.json())
384
+
385
+ except Exception as e:
386
+ return JSONResponse(
387
+ {"error": str(e)},
388
+ status_code=500
389
+ )
390
+
391
+ @app.get("/api/tags")
392
+ async def tags():
393
+ """List available models"""
394
+ try:
395
+ response = requests.get("http://localhost:11434/api/tags")
396
+ return JSONResponse(response.json())
397
+ except:
398
+ return JSONResponse({"models": []})
399
+
400
+ @app.get("/health")
401
+ async def health():
402
+ """Health check endpoint"""
403
+ try:
404
+ response = requests.get("http://localhost:11434/api/tags", timeout=5)
405
+ if response.status_code == 200:
406
+ return {"status": "healthy", "ollama": "running"}
407
+ except:
408
+ pass
409
+ return {"status": "degraded", "ollama": "unavailable"}
410
+
411
+ if __name__ == "__main__":
412
+ import uvicorn
413
+ uvicorn.run(app, host="0.0.0.0", port=7860)
start.sh ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ echo "πŸš€ Starting AJ STUDIOZ..."
4
+
5
+ # Set Ollama home
6
+ export OLLAMA_HOME=/home/user/.ollama
7
+ mkdir -p $OLLAMA_HOME
8
+
9
+ # Start Ollama server in background
10
+ echo "πŸ”§ Starting Ollama server..."
11
+ ollama serve > /tmp/ollama.log 2>&1 &
12
+
13
+ # Wait for Ollama to be ready
14
+ echo "⏳ Waiting for Ollama..."
15
+ for i in {1..30}; do
16
+ if curl -s http://localhost:11434/api/tags > /dev/null 2>&1; then
17
+ echo "βœ… Ollama is ready!"
18
+ break
19
+ fi
20
+ sleep 2
21
+ done
22
+
23
+ # Pull base model
24
+ echo "πŸ“₯ Downloading qwen2:0.5b (this may take a few minutes)..."
25
+ ollama pull qwen2:0.5b
26
+
27
+ # Create AJ model (Claude-like version)
28
+ echo "🎨 Creating AJ model with enhanced capabilities..."
29
+ ollama create aj-mini -f /app/Modelfile-AJ-Mini
30
+
31
+ # Verify model creation
32
+ if ollama list | grep -q "aj-mini"; then
33
+ echo "βœ… AJ model created successfully!"
34
+ else
35
+ echo "⚠️ Warning: AJ model may not have been created properly"
36
+ fi
37
+
38
+ echo "βœ… AJ-Mini ready!"
39
+
40
+ # List models
41
+ echo "πŸ“‹ Available models:"
42
+ ollama list
43
+
44
+ # Start FastAPI server
45
+ echo "🌐 Starting API server on port 7860..."
46
+ exec python /app/app.py