Spaces:
Running on Zero
Running on Zero
| #!/usr/bin/env python3 | |
| """ | |
| Frox AI Morph 1.1 — Interactive Chat CLI | |
| Usage: | |
| python scripts/chat.py --model ./frox-morph-1-1-output/sft_final | |
| python scripts/chat.py --model ./frox-morph-1-1-output/sft_final --image cat.jpg | |
| python scripts/chat.py --model ./frox-morph-1-1-output/sft_final --quantization 4bit | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| import sys | |
| from pathlib import Path | |
| sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) | |
| from inference.engine.morph_engine import MorphInferenceEngine | |
| from utils.common import print_banner | |
| SYSTEM_PROMPT = ( | |
| "You are Frox AI Morph 1.1, a highly capable multimodal AI assistant. " | |
| "You can understand text, images, and video. You can search the web, " | |
| "run code, generate images and videos. Always be helpful, accurate, " | |
| "safe, and honest." | |
| ) | |
| def main(): | |
| parser = argparse.ArgumentParser(description="Chat with Frox AI Morph 1.1") | |
| parser.add_argument("--model", type=str, required=True, help="Path to saved model dir") | |
| parser.add_argument("--image", type=str, default=None, help="Optional image to discuss") | |
| parser.add_argument("--quantization", choices=["4bit", "8bit"], default=None) | |
| parser.add_argument("--max-tokens", type=int, default=1024) | |
| parser.add_argument("--temperature", type=float, default=0.7) | |
| parser.add_argument("--session", action="store_true", | |
| help="Use persistent KV-cache session mode (faster multi-turn)") | |
| args = parser.parse_args() | |
| print_banner() | |
| engine = MorphInferenceEngine.from_pretrained( | |
| args.model, quantization=args.quantization, | |
| ) | |
| pixel_values = None | |
| if args.image: | |
| from PIL import Image | |
| img = Image.open(args.image).convert("RGB") | |
| pixel_values = engine.model.vision_module.preprocess_image(img, device=engine.device) | |
| print(f"🖼 Loaded image: {args.image}\n") | |
| print("Type your message. Commands: /reset /think /quit\n") | |
| messages = [] | |
| session_id = "cli-session" | |
| show_thinking = False | |
| while True: | |
| try: | |
| user_input = input("You: ").strip() | |
| except (EOFError, KeyboardInterrupt): | |
| print("\nGoodbye!") | |
| break | |
| if not user_input: | |
| continue | |
| if user_input == "/quit": | |
| break | |
| if user_input == "/reset": | |
| messages = [] | |
| engine.reset_session(session_id) | |
| print("(conversation reset)\n") | |
| continue | |
| if user_input == "/think": | |
| show_thinking = not show_thinking | |
| print(f"(thinking display: {'on' if show_thinking else 'off'})\n") | |
| continue | |
| print("Morph: ", end="", flush=True) | |
| if args.session: | |
| response = engine.chat( | |
| session_id, user_input, system_prompt=SYSTEM_PROMPT, | |
| max_new_tokens=args.max_tokens, temperature=args.temperature, | |
| stream_callback=lambda chunk: print(chunk, end="", flush=True), | |
| ) | |
| print() | |
| else: | |
| messages.append({"role": "user", "content": user_input}) | |
| response_parts = [] | |
| for chunk in engine.generate_stream( | |
| messages, system_prompt=SYSTEM_PROMPT, | |
| max_new_tokens=args.max_tokens, temperature=args.temperature, | |
| pixel_values=pixel_values, | |
| ): | |
| print(chunk, end="", flush=True) | |
| response_parts.append(chunk) | |
| response = "".join(response_parts) | |
| print() | |
| messages.append({"role": "assistant", "content": response}) | |
| thinking, answer = engine.parse_thinking(response) | |
| if thinking and show_thinking: | |
| print(f"\n💭 [thinking]: {thinking}\n") | |
| tool_calls = engine.parse_tool_calls(response) | |
| if tool_calls: | |
| print(f"\n🔧 [tool calls detected]: {tool_calls}") | |
| gen_requests = engine.parse_generation_requests(response) | |
| if gen_requests: | |
| print(f"\n🎨 [generation requests]: {gen_requests}") | |
| print() | |
| if __name__ == "__main__": | |
| main() | |