alperugurcan's picture
Upload 4 files
f509df8 verified
Raw
History Blame Contribute Delete
2.19 kB
"""Modal endpoint for Photo Archaeology Simulator text generation.
Deploy with:
modal deploy modal_app.py
Then set the Hugging Face Space secret MODAL_EXCAVATE_URL to the printed /excavate URL.
"""
import modal
MODEL_ID = "Qwen/Qwen3-4B-Instruct-2507"
image = (
modal.Image.debian_slim(python_version="3.11")
.pip_install("fastapi[standard]", "torch", "transformers>=4.51.0", "accelerate", "sentencepiece")
)
app = modal.App("photo-archaeology-simulator")
@app.cls(image=image, gpu="A10G", timeout=240, scaledown_window=300)
class ArchaeologyWriter:
@modal.enter()
def load(self):
from transformers import AutoModelForCausalLM, AutoTokenizer
self.tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
self.model = AutoModelForCausalLM.from_pretrained(MODEL_ID, device_map="auto", torch_dtype="auto")
@modal.method()
def write(self, artifacts, tone):
prompt = f"""
You are a comic academic archaeologist studying messy modern rooms.
Write a faux-scholarly excavation report in markdown.
Tone: {tone}
Use numbered Clue entries matching these detected artifacts: {artifacts}
Invent playful carbon-dating methods for digital and household objects.
Keep it funny, kind, and under 700 words. Do not give real cleaning advice except as a joke.
""".strip()
messages = [
{"role": "system", "content": "You produce humorous pseudo-academic reports, never serious scientific claims."},
{"role": "user", "content": prompt},
]
text = self.tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
inputs = self.tokenizer([text], return_tensors="pt").to(self.model.device)
output = self.model.generate(**inputs, max_new_tokens=900, temperature=0.85, do_sample=True)
return self.tokenizer.decode(output[0][inputs.input_ids.shape[1]:], skip_special_tokens=True)
@app.function(image=image, timeout=300)
@modal.fastapi_endpoint(method="POST")
def excavate(payload: dict):
report = ArchaeologyWriter().write.remote(payload.get("artifacts", []), payload.get("tone", "Very academic"))
return {"model": MODEL_ID, "report": report}