Spaces:
Paused
Paused
Download api.py from bankrlebhai/freellm: direct link, hf CLI and curl.
- Browser
- Download file 4.24 kB
-
https://huggingface.co/spaces/bankrlebhai/freellm/resolve/main/api.py
- Command line
-
hf download hf://spaces/bankrlebhai/freellm/api.py
-
curl -L -o api.py https://huggingface.co/spaces/bankrlebhai/freellm/resolve/main/api.py
4.24 kB
| from fastapi import FastAPI, Request | |
| from fastapi.responses import StreamingResponse, JSONResponse | |
| from llm_manager import LLMManager | |
| import json | |
| import time | |
| import asyncio | |
| from typing import Optional | |
| app = FastAPI() | |
| llm = None | |
| async def startup_event(): | |
| global llm | |
| llm = LLMManager() | |
| async def root(): | |
| return {"status": "running", "model": llm.model_file if llm else "loading"} | |
| async def generate(request: Request): | |
| data = await request.json() | |
| prompt = data.get("prompt") | |
| stream = data.get("stream", True) | |
| model_name = data.get("model", "qwen3") | |
| if not prompt: | |
| return JSONResponse({"error": "Prompt is required"}, status_code=400) | |
| def stream_response(): | |
| response = llm.generate(prompt, stream=True) | |
| for chunk in response: | |
| yield json.dumps({ | |
| "model": model_name, | |
| "created_at": time.strftime("%Y-%m-%dT%H:%M:%S.000Z", time.gmtime()), | |
| "response": chunk["choices"][0]["text"], | |
| "done": False | |
| }) + "\n" | |
| yield json.dumps({ | |
| "model": model_name, | |
| "created_at": time.strftime("%Y-%m-%dT%H:%M:%S.000Z", time.gmtime()), | |
| "done": True, | |
| "context": [], # Placeholder | |
| "total_duration": 0, | |
| "load_duration": 0, | |
| "prompt_eval_count": 0, | |
| "prompt_eval_duration": 0, | |
| "eval_count": 0, | |
| "eval_duration": 0 | |
| }) + "\n" | |
| if stream: | |
| return StreamingResponse(stream_response(), media_type="application/x-ndjson") | |
| else: | |
| response = llm.generate(prompt, stream=False) | |
| return { | |
| "model": model_name, | |
| "created_at": time.strftime("%Y-%m-%dT%H:%M:%S.000Z", time.gmtime()), | |
| "response": response["choices"][0]["text"], | |
| "done": True, | |
| "context": [], | |
| "total_duration": 0, | |
| "load_duration": 0, | |
| "prompt_eval_count": 0, | |
| "prompt_eval_duration": 0, | |
| "eval_count": 0, | |
| "eval_duration": 0 | |
| } | |
| async def chat(request: Request): | |
| data = await request.json() | |
| messages = data.get("messages", []) | |
| stream = data.get("stream", True) | |
| model_name = data.get("model", "qwen3") | |
| def stream_chat(): | |
| response = llm.chat_completion(messages, stream=True) | |
| for chunk in response: | |
| if "choices" in chunk and len(chunk["choices"]) > 0: | |
| delta = chunk["choices"][0].get("delta", {}) | |
| content = delta.get("content", "") | |
| yield json.dumps({ | |
| "model": model_name, | |
| "created_at": time.strftime("%Y-%m-%dT%H:%M:%S.000Z", time.gmtime()), | |
| "message": {"role": "assistant", "content": content}, | |
| "done": False | |
| }) + "\n" | |
| yield json.dumps({ | |
| "model": model_name, | |
| "created_at": time.strftime("%Y-%m-%dT%H:%M:%S.000Z", time.gmtime()), | |
| "done": True | |
| }) + "\n" | |
| if stream: | |
| return StreamingResponse(stream_chat(), media_type="application/x-ndjson") | |
| else: | |
| response = llm.chat_completion(messages, stream=False) | |
| return { | |
| "model": model_name, | |
| "created_at": time.strftime("%Y-%m-%dT%H:%M:%S.000Z", time.gmtime()), | |
| "message": response["choices"][0]["message"], | |
| "done": True | |
| } | |
| async def tags(): | |
| return { | |
| "models": [ | |
| { | |
| "name": "qwen3", | |
| "modified_at": time.strftime("%Y-%m-%dT%H:%M:%S.000Z", time.gmtime()), | |
| "size": 0, # TBD | |
| "digest": "qwen3-digest", | |
| "details": { | |
| "format": "gguf", | |
| "family": "qwen", | |
| "families": ["qwen"], | |
| "parameter_size": "14B", | |
| "quantization_level": "Q4_K_M" | |
| } | |
| } | |
| ] | |
| } | |
| if __name__ == "__main__": | |
| import uvicorn | |
| uvicorn.run(app, host="0.0.0.0", port=7860) | |