hadadrjt commited on
Commit
eb36b93
·
0 Parent(s):

api: Initial.

Browse files
Files changed (3) hide show
  1. README.md +14 -0
  2. app.py +179 -0
  3. requirements.txt +4 -0
README.md ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: J.A.R.V.I.S. API Endpoint
3
+ license: apache-2.0
4
+ license_link: https://huggingface.co/hadadrjt/JARVIS/blob/main/LICENSE
5
+ emoji: 👀
6
+ colorFrom: green
7
+ colorTo: green
8
+ sdk: gradio
9
+ sdk_version: 5.34.0
10
+ app_file: app.py
11
+ pinned: false
12
+ models:
13
+ - hadadrjt/JARVIS
14
+ ---
app.py ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # SPDX-FileCopyrightText: Hadad <hadad@linuxmail.org>
3
+ # SPDX-License-Identifier: Apache-2.0
4
+ #
5
+
6
+ import json
7
+ import time
8
+ import uuid
9
+ import uvicorn
10
+
11
+ from contextlib import asynccontextmanager
12
+ from fastapi import FastAPI, HTTPException
13
+ from fastapi.responses import JSONResponse, StreamingResponse
14
+ from gradio_client import Client
15
+ from pydantic import BaseModel
16
+ from typing import AsyncGenerator, Optional
17
+
18
+ # Default AI model
19
+ MODEL = "JARVIS: 2.1.3"
20
+
21
+ # Global Gradio client instance
22
+ jarvis: Optional[Client] = None
23
+
24
+ @asynccontextmanager
25
+ async def lifespan(app: FastAPI):
26
+ """
27
+ Initialize Gradio client at app startup.
28
+ """
29
+ global jarvis
30
+ print("Initializing Gradio AI client...")
31
+ try:
32
+ jarvis = Client("hadadrjt/ai")
33
+ print(f"Connected to Gradio AI client at: {jarvis.src}")
34
+
35
+ jarvis.predict(new=MODEL, api_name="/change_model")
36
+ print(f"Default model set to: {MODEL}")
37
+
38
+ yield
39
+ except Exception as e:
40
+ print(f"Error initializing Gradio client: {e}")
41
+ yield
42
+
43
+ app = FastAPI(lifespan=lifespan)
44
+
45
+ class ResponseRequest(BaseModel):
46
+ """
47
+ Request body for /v1/responses endpoint.
48
+ - model: AI model to use (optional).
49
+ - input: User input text.
50
+ - stream: Whether to stream response.
51
+ """
52
+ model: Optional[str] = MODEL
53
+ input: str
54
+ stream: Optional[bool] = False
55
+
56
+ async def event_generator(user_input: str, model: str) -> AsyncGenerator[str, None]:
57
+ """
58
+ Stream incremental AI responses (deltas) as Server-Sent Events.
59
+ """
60
+ global jarvis
61
+
62
+ if model != MODEL:
63
+ jarvis.predict(new=model, api_name="/change_model")
64
+
65
+ jarvis_response = jarvis.submit(multi={"text": user_input}, api_name="/api")
66
+
67
+ buffer = ""
68
+
69
+ try:
70
+ for partial in jarvis_response:
71
+ text = partial[0][0][1]
72
+
73
+ if text.startswith(buffer):
74
+ delta = text[len(buffer):]
75
+ else:
76
+ delta = text
77
+
78
+ buffer = text
79
+
80
+ # Skip empty chunks
81
+ if delta == "":
82
+ continue
83
+
84
+ chunk = {
85
+ "id": f"chatcmpl-{uuid.uuid4().hex[:8]}",
86
+ "object": "chat.completion.chunk",
87
+ "created": int(time.time()),
88
+ "model": model,
89
+ "choices": [
90
+ {
91
+ "index": 0,
92
+ "delta": {"content": delta},
93
+ "finish_reason": None
94
+ }
95
+ ]
96
+ }
97
+
98
+ yield f"data: {json.dumps(chunk)}\n\n"
99
+
100
+ # Final chunk to signal completion
101
+ done_chunk = {
102
+ "id": f"chatcmpl-{uuid.uuid4().hex[:8]}",
103
+ "object": "chat.completion.chunk",
104
+ "created": int(time.time()),
105
+ "model": model,
106
+ "choices": [
107
+ {
108
+ "index": 0,
109
+ "delta": {},
110
+ "finish_reason": "stop"
111
+ }
112
+ ]
113
+ }
114
+ yield f"data: {json.dumps(done_chunk)}\n\n"
115
+
116
+ except Exception as e:
117
+ error_chunk = {
118
+ "error": {"message": f"Streaming error: {str(e)}"}
119
+ }
120
+ yield f"data: {json.dumps(error_chunk)}\n\n"
121
+
122
+ @app.post("/v1/responses")
123
+ async def responses(req: ResponseRequest):
124
+ """
125
+ Main endpoint to get AI response.
126
+ Supports streaming or full JSON response.
127
+ """
128
+ global jarvis
129
+
130
+ if jarvis is None:
131
+ raise HTTPException(status_code=503, detail="AI service not initialized or failed to connect.")
132
+
133
+ user_input = req.input
134
+ model = req.model or MODEL
135
+
136
+ if req.stream:
137
+ return StreamingResponse(event_generator(user_input, model), media_type="text/event-stream")
138
+
139
+ if model != MODEL:
140
+ jarvis.predict(new=model, api_name="/change_model")
141
+
142
+ jarvis_response = jarvis.submit(multi={"text": user_input}, api_name="/api")
143
+
144
+ buffer = ""
145
+ for partial in jarvis_response:
146
+ text = partial[0][0][1]
147
+ buffer = text
148
+
149
+ response = {
150
+ "id": f"chatcmpl-{uuid.uuid4().hex[:8]}",
151
+ "object": "chat.completion",
152
+ "created": int(time.time()),
153
+ "model": model,
154
+ "choices": [
155
+ {
156
+ "index": 0,
157
+ "message": {
158
+ "role": "assistant",
159
+ "content": buffer
160
+ },
161
+ "finish_reason": "stop"
162
+ }
163
+ ]
164
+ }
165
+
166
+ return JSONResponse(response)
167
+
168
+ @app.get("/")
169
+ def root():
170
+ """
171
+ Health check endpoint.
172
+ """
173
+ if jarvis:
174
+ return {"status": "API is running", "jarvis_service": True}
175
+ else:
176
+ return {"status": "API is running", "jarvis_service": False, "message": "AI service not ready."}
177
+
178
+ if __name__ == "__main__":
179
+ uvicorn.run(app, host="0.0.0.0", port=7860)
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ fastapi
2
+ uvicorn
3
+ gradio_client
4
+ rich