omkar1804 commited on
Commit
06f002d
·
verified ·
1 Parent(s): b6f9362

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +169 -0
app.py ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import re
4
+
5
+ import spaces
6
+ import gradio as gr
7
+ import torch
8
+ from transformers import AutoModelForCausalLM, AutoTokenizer
9
+
10
+
11
+ MODEL_ID = "prem-research/prem-1B-SQL"
12
+ MODEL_REVISION = "44dd7fcf9227af4efed936bf29323c61bf66aad1"
13
+
14
+ MAX_INPUT_TOKENS = 3072
15
+ DEFAULT_MAX_NEW_TOKENS = 256
16
+ MAX_NEW_TOKENS = 512
17
+
18
+ tokenizer = AutoTokenizer.from_pretrained(
19
+ MODEL_ID,
20
+ revision=MODEL_REVISION,
21
+ use_fast=True,
22
+ )
23
+
24
+ if tokenizer.pad_token_id is None:
25
+ tokenizer.pad_token = tokenizer.eos_token
26
+
27
+ # ZeroGPU requires the GPU model to be placed on CUDA at module load time.
28
+ model = (
29
+ AutoModelForCausalLM.from_pretrained(
30
+ MODEL_ID,
31
+ revision=MODEL_REVISION,
32
+ dtype=torch.float16,
33
+ use_safetensors=True,
34
+ )
35
+ .to("cuda")
36
+ .eval()
37
+ )
38
+
39
+ SQL_START = re.compile(r"\b(?:WITH|SELECT)\b", re.IGNORECASE)
40
+ CODE_BLOCK = re.compile(
41
+ r"```(?:sql)?\s*(.*?)```",
42
+ re.IGNORECASE | re.DOTALL,
43
+ )
44
+
45
+ EXAMPLE_PROMPT = """Write exactly one read-only SQLite query.
46
+ Use only the tables and columns in the schema.
47
+ Return SQL only, without Markdown or explanation.
48
+
49
+ Database schema:
50
+
51
+ CREATE TABLE customers (
52
+ id INTEGER PRIMARY KEY,
53
+ name TEXT NOT NULL,
54
+ city TEXT
55
+ );
56
+
57
+ Question: How many customers are there?
58
+
59
+ SQL:
60
+ """
61
+
62
+
63
+ def extract_sql(generated: str) -> str:
64
+ text = generated.strip()
65
+
66
+ fenced = CODE_BLOCK.search(text)
67
+ if fenced:
68
+ text = fenced.group(1).strip()
69
+
70
+ start = SQL_START.search(text)
71
+ if start:
72
+ text = text[start.start():]
73
+
74
+ return text.removesuffix("```").strip()
75
+
76
+
77
+ @spaces.GPU(duration=45)
78
+ def generate_sql(prompt: str, max_new_tokens: int) -> str:
79
+ prompt = (prompt or "").strip()
80
+
81
+ if not prompt:
82
+ raise gr.Error("Prompt cannot be empty.")
83
+
84
+ token_limit = max(
85
+ 32,
86
+ min(MAX_NEW_TOKENS, int(max_new_tokens or DEFAULT_MAX_NEW_TOKENS)),
87
+ )
88
+
89
+ inputs = tokenizer(
90
+ prompt,
91
+ return_tensors="pt",
92
+ add_special_tokens=True,
93
+ truncation=False,
94
+ )
95
+
96
+ input_length = int(inputs["input_ids"].shape[-1])
97
+ if input_length > MAX_INPUT_TOKENS:
98
+ raise gr.Error(
99
+ f"Prompt has {input_length:,} tokens; "
100
+ f"the maximum is {MAX_INPUT_TOKENS:,}."
101
+ )
102
+
103
+ inputs = {
104
+ name: tensor.to("cuda")
105
+ for name, tensor in inputs.items()
106
+ }
107
+
108
+ with torch.inference_mode():
109
+ output = model.generate(
110
+ **inputs,
111
+ max_new_tokens=token_limit,
112
+ do_sample=False,
113
+ eos_token_id=tokenizer.eos_token_id,
114
+ pad_token_id=tokenizer.pad_token_id,
115
+ use_cache=True,
116
+ )
117
+
118
+ new_tokens = output[0, input_length:]
119
+ generated = tokenizer.decode(
120
+ new_tokens,
121
+ skip_special_tokens=True,
122
+ )
123
+
124
+ sql = extract_sql(generated)
125
+ if not sql:
126
+ raise gr.Error("The model returned an empty response.")
127
+
128
+ return sql
129
+
130
+
131
+ with gr.Blocks(title="Prem 1B SQL API") as demo:
132
+ gr.Markdown(
133
+ """
134
+ # Prem 1B SQL
135
+
136
+ Generate SQL from a schema-aware natural-language prompt.
137
+ The calling application must validate all generated SQL.
138
+ """
139
+ )
140
+
141
+ prompt_input = gr.Textbox(
142
+ value=EXAMPLE_PROMPT,
143
+ label="Schema-aware prompt",
144
+ lines=18,
145
+ )
146
+
147
+ max_tokens_input = gr.Slider(
148
+ minimum=32,
149
+ maximum=MAX_NEW_TOKENS,
150
+ value=DEFAULT_MAX_NEW_TOKENS,
151
+ step=1,
152
+ label="Maximum output tokens",
153
+ )
154
+
155
+ generate_button = gr.Button("Generate SQL", variant="primary")
156
+ sql_output = gr.Code(label="Generated SQL", language="sql")
157
+
158
+ generate_button.click(
159
+ fn=generate_sql,
160
+ inputs=[prompt_input, max_tokens_input],
161
+ outputs=sql_output,
162
+ api_name="generate",
163
+ concurrency_limit=1,
164
+ )
165
+
166
+ demo.queue(max_size=20, default_concurrency_limit=1)
167
+
168
+ if __name__ == "__main__":
169
+ demo.launch()