Instructions to use Subject-Emu-5259/NeuralAI with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use Subject-Emu-5259/NeuralAI with PEFT:
Task type is invalid.
- Notebooks
- Google Colab
- Kaggle
| #!/usr/bin/env python3 | |
| """ | |
| NeuralAI Model Service | |
| - Loads model once on startup | |
| - Keeps in memory | |
| - Exposes inference API on port 7001 | |
| - Handles both sync and streaming responses | |
| """ | |
| import os | |
| import sys | |
| import json | |
| import torch | |
| from pathlib import Path | |
| from flask import Flask, Response, jsonify, request | |
| from datetime import datetime | |
| # CPU optimization | |
| torch.set_num_threads(4) | |
| # Configuration | |
| PORT = int(os.environ.get("MODEL_PORT", "7001")) | |
| MODEL_PATH = os.environ.get("MODEL_PATH", "/home/workspace/Projects/NeuralAI/checkpoints/v2_model") | |
| BASE_MODEL = os.environ.get("BASE_MODEL", "HuggingFaceTB/SmolLM2-360M-Instruct") | |
| app = Flask(__name__) | |
| # Global model state | |
| model = None | |
| tokenizer = None | |
| model_status = "loading" | |
| model_error = None | |
| inference_count = 0 | |
| def load_model(): | |
| """Load model once on startup.""" | |
| global model, tokenizer, model_status, model_error | |
| print(f"[Model Service] Loading model from {MODEL_PATH}") | |
| print(f"[Model Service] Base model: {BASE_MODEL}") | |
| try: | |
| from transformers import AutoModelForCausalLM, AutoTokenizer | |
| from peft import PeftModel | |
| # Load tokenizer | |
| tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL) | |
| tokenizer.pad_token = tokenizer.eos_token | |
| # Check for adapter | |
| adapter_path = Path(MODEL_PATH) | |
| adapter_bin = adapter_path / "adapter_model.bin" | |
| adapter_safetensors = adapter_path / "adapter_model.safetensors" | |
| if adapter_path.exists() and (adapter_bin.exists() or adapter_safetensors.exists()): | |
| print(f"[Model Service] Loading with LoRA adapter...") | |
| base = AutoModelForCausalLM.from_pretrained( | |
| BASE_MODEL, | |
| torch_dtype=torch.float32, | |
| device_map=None, | |
| low_cpu_mem_usage=True | |
| ) | |
| model = PeftModel.from_pretrained(base, str(adapter_path)) | |
| print(f"[Model Service] LoRA adapter loaded!") | |
| else: | |
| print(f"[Model Service] Loading base model only...") | |
| model = AutoModelForCausalLM.from_pretrained( | |
| BASE_MODEL, | |
| torch_dtype=torch.float32, | |
| device_map=None, | |
| low_cpu_mem_usage=True | |
| ) | |
| model.eval() | |
| model_status = "ready" | |
| model_error = None | |
| params = sum(p.numel() for p in model.parameters()) | |
| print(f"[Model Service] ✓ Model ready! Parameters: {params:,}") | |
| print(f"[Model Service] Listening on port {PORT}") | |
| except Exception as e: | |
| import traceback | |
| model_status = "error" | |
| model_error = str(e) | |
| print(f"[Model Service] ✗ Failed to load model: {e}") | |
| traceback.print_exc() | |
| def health(): | |
| """Health check endpoint.""" | |
| return jsonify({ | |
| "status": model_status, | |
| "error": model_error, | |
| "inference_count": inference_count, | |
| "model": BASE_MODEL, | |
| "port": PORT | |
| }) | |
| def status(): | |
| """Detailed status endpoint.""" | |
| return jsonify({ | |
| "status": model_status, | |
| "error": model_error, | |
| "inference_count": inference_count, | |
| "model_loaded": model is not None, | |
| "tokenizer_loaded": tokenizer is not None, | |
| "model_path": MODEL_PATH, | |
| "base_model": BASE_MODEL, | |
| "device": "cpu", | |
| "threads": 4 | |
| }) | |
| def generate(): | |
| """Generate text response (non-streaming).""" | |
| global inference_count | |
| if model is None or tokenizer is None: | |
| return jsonify({"error": "Model not loaded", "status": model_status}), 503 | |
| try: | |
| data = request.get_json() | |
| prompt = data.get("prompt", "") | |
| max_tokens = data.get("max_tokens", 256) | |
| temperature = data.get("temperature", 0.7) | |
| if not prompt: | |
| return jsonify({"error": "No prompt provided"}), 400 | |
| # Build full prompt with chat template | |
| if not prompt.startswith("<|im_start|>"): | |
| full_prompt = f"<|im_start|>user\n{prompt}<|im_end|>\n<|im_start|>assistant\n" | |
| else: | |
| full_prompt = prompt | |
| # Tokenize | |
| inputs = tokenizer(full_prompt, return_tensors="pt") | |
| # Generate | |
| with torch.no_grad(): | |
| outputs = model.generate( | |
| **inputs, | |
| max_new_tokens=max_tokens, | |
| do_sample=True, | |
| temperature=temperature, | |
| top_p=0.95, | |
| pad_token_id=tokenizer.eos_token_id | |
| ) | |
| # Decode only new tokens | |
| new_tokens = outputs[0][inputs["input_ids"].shape[-1]:] | |
| response = tokenizer.decode(new_tokens, skip_special_tokens=True) | |
| inference_count += 1 | |
| return jsonify({ | |
| "response": response, | |
| "tokens_generated": len(new_tokens), | |
| "inference_count": inference_count | |
| }) | |
| except Exception as e: | |
| return jsonify({"error": str(e)}), 500 | |
| def generate_stream(): | |
| """Generate text response with streaming.""" | |
| global inference_count | |
| if model is None or tokenizer is None: | |
| return jsonify({"error": "Model not loaded"}), 503 | |
| try: | |
| from transformers import TextIteratorStreamer | |
| import threading | |
| data = request.get_json() | |
| prompt = data.get("prompt", "") | |
| max_tokens = data.get("max_tokens", 256) | |
| temperature = data.get("temperature", 0.7) | |
| if not prompt: | |
| return jsonify({"error": "No prompt provided"}), 400 | |
| # Build full prompt | |
| if not prompt.startswith("<|im_start|>"): | |
| full_prompt = f"<|im_start|>user\n{prompt}<|im_end|>\n<|im_start|>assistant\n" | |
| else: | |
| full_prompt = prompt | |
| inputs = tokenizer(full_prompt, return_tensors="pt") | |
| # Create streamer | |
| streamer = TextIteratorStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True) | |
| # Run generation in thread | |
| thread = threading.Thread(target=model.generate, kwargs=dict( | |
| **inputs, | |
| streamer=streamer, | |
| max_new_tokens=max_tokens, | |
| do_sample=True, | |
| temperature=temperature, | |
| top_p=0.95, | |
| pad_token_id=tokenizer.eos_token_id | |
| )) | |
| thread.start() | |
| def generate(): | |
| for token in streamer: | |
| yield f"data: {json.dumps({'token': token})}\n\n" | |
| yield "data: [DONE]\n\n" | |
| inference_count += 1 | |
| return Response( | |
| generate(), | |
| mimetype="text/event-stream", | |
| headers={"Cache-Control": "no-cache", "X-Accel-Buffering": "no"} | |
| ) | |
| except Exception as e: | |
| return jsonify({"error": str(e)}), 500 | |
| # Load model on startup | |
| print(f"[Model Service] Starting...") | |
| print(f"[Model Service] Port: {PORT}") | |
| load_model() | |
| if __name__ == "__main__": | |
| app.run(host="0.0.0.0", port=PORT, debug=False, threaded=True) | |