| from transformers import pipeline |
| import gradio as gr |
| import spaces |
| import os |
| import time |
| from collections import defaultdict |
|
|
| |
| |
| hf_token = os.getenv("HF_TOKEN") |
| pipe = pipeline("text-generation", model="markrodrigo/Llama-3.2-3B-Instruct-Spatial-SQL-1.1", device_map="auto", token=hf_token) |
|
|
| usage_tracker = defaultdict(list) |
| MAX_REQUESTS_PER_DAY = 3 |
| TRUSTED_USERS = {"markrodrigo"} |
|
|
| |
| ALPACA_TEMPLATE = """<|begin_of_text|><|start_header_id|>system<|end_header_id|> You are a helpful assistant. You are an expert at PostGIS and Postgresql and SQL and psql. <|eot_id|><|start_header_id|>user<|end_header_id|> |
| |
| ### Instruction: Write a PostGIS SQL statement for the following. |
| {instruction} |
| |
| ### Input: |
| {input} |
| |
| ### Response: |
| <|eot_id|><|start_header_id|>assistant<|end_header_id|> |
| """ |
|
|
| |
| PRESET_EXAMPLES = [ |
| "What is the area for the polygon? : 'Polygon ((-3.7515154 40.3855551, -3.7514972 40.3856581, -3.7507005 40.3855767, -3.7507167 40.3854722, -3.7515154 40.3855551))'", |
| "What is the centroid for the polygon? : 'Polygon ((-3.6934636 40.4808785, -3.6933352 40.4811486, -3.6930125 40.4810598, -3.693141 40.4807897, -3.6934636 40.4808785))'", |
| "What is the thousand meter buffer for the following point? : 'Point(-8.7522658 41.3862664)'", |
| "How long is the line? : 'LINESTRING (-3.6976693 40.4263178, -3.6986082 40.4258729)'", |
| "How far apart is the point and line? : 'Point(-109.87549823 38.60574249)' 'LineString(-109.24324628 38.76349931, -109.4821773 38.6875815)'" |
| ] |
|
|
| |
| custom_css = """ |
| #special-button { |
| background-color: #0052FF !important; /* Your desired color */ |
| color: white !important; |
| border: none !important; |
| font-weight: 600 !important; |
| padding: 12px 24px !important; |
| } |
| |
| #special-button:hover { |
| background-color: #CAD3DE !important; |
| transform: scale(1.03); |
| transition: all 0.2s ease; |
| } |
| |
| #clear-chat-btn { |
| width: 200px !important; |
| min-width: 200px !important; |
| max-width: 200px !important; |
| height: 42px !important; |
| background-color: #FF5733 !important; /* Main hex color */ |
| color: #FFFFFF !important; /* White text */ |
| border: none !important; |
| font-size: 14px !important; |
| font-weight: 600 !important; |
| padding: 8px 16px !important; |
| border-radius: 8px !important; /* Optional rounded look */ |
| } |
| |
| #clear-chat-btn:hover { |
| background-color: #C70039 !important; /* Hover hex color (darker) */ |
| transform: translateY(-1px); |
| box-shadow: 0 4px 12px rgba(199, 0, 57, 0.3) !important; |
| } |
| """ |
| global_counter = 0 |
|
|
| |
| |
| |
|
|
| def increment_counter(): |
| global global_counter |
| global_counter += 1 |
| return global_counter |
|
|
| @spaces.GPU |
| def respond(user_message, chat_history, profile: gr.OAuthProfile | None): |
| |
| if profile is None: |
| raise gr.Error("You must be logged in with a Hugging Face account to use this demo.") |
| |
| username = profile.username |
| print("Debug username:", username) |
| |
| now = time.time() |
| usage_tracker[username] = [ts for ts in usage_tracker[username] if now - ts < 86400] |
| |
| |
| if username in TRUSTED_USERS: |
| pass |
| else: |
| if len(usage_tracker[username]) >= MAX_REQUESTS_PER_DAY: |
| raise gr.Error(f"Daily limit reached ({MAX_REQUESTS_PER_DAY} requests/day).") |
| |
| usage_tracker[username].append(now) |
|
|
| |
| |
|
|
|
|
| |
| |
|
|
| chat_history = chat_history or [] |
|
|
| if not user_message or not user_message.strip(): |
| return chat_history, "" |
|
|
| |
| chat_history.append({"role": "user", "content": user_message}) |
| chat_history.append({"role": "assistant", "content": None}) |
|
|
| prompt = ALPACA_TEMPLATE.format(instruction=user_message, input="") |
|
|
| sequences = pipe( |
| prompt, |
| max_new_tokens=256, |
| return_full_text=False, |
| temperature=0.4, |
| top_k=100, |
| do_sample=True, |
| ) |
|
|
| bot_response = sequences[0]["generated_text"].strip() |
| chat_history[-1]["content"] = bot_response |
|
|
| return chat_history, "", global_counter |
|
|
|
|
|
|
| with gr.Blocks(title="Text to PostGIS Postgresql via Llama 3.2") as demo: |
| gr.LoginButton() |
| gr.Markdown("# Natural Language to Spatial SQL.\n### Convert natural language and spatial primitives to PostGIS with Llama 3.2") |
| chatbot = gr.Chatbot( |
| label="Chat", |
| height=400, |
| |
| |
| ) |
|
|
| with gr.Row(): |
| with gr.Column(scale=5): |
| msg = gr.Textbox( |
| placeholder="Natural Language : WKT format", |
| lines=2, |
| container=False |
| ) |
| with gr.Column(scale=1, min_width=100): |
| submit_btn = gr.Button("Submit", variant="primary", elem_id="special-button" ) |
|
|
| gr.Markdown("### Quick Examples") |
| gr.Examples( |
| examples=PRESET_EXAMPLES, |
| inputs=msg, |
| label="Click an example → then click Submit" |
| ) |
| |
| |
| |
|
|
|
|
| clear_btn = gr.Button("Clear Chat", elem_id="clear-chat-btn") |
| clear_btn.click(lambda: ([], ""), outputs=[chatbot, msg]) |
| gr.Markdown("## 🚀 Space Request Tracker") |
| |
| counter_display = gr.Number(value=global_counter, label="Global Counter") |
|
|
| submit_btn.click(fn=respond, inputs=[msg, chatbot], outputs=[chatbot, msg, counter_display]).then( |
| fn=increment_counter, |
| inputs=[], |
| outputs=counter_display |
| ) |
| msg.submit(fn=respond, inputs=[msg, chatbot], outputs=[chatbot, msg, counter_display]) |
| |
|
|
| |
| |
| demo.load(fn=lambda: global_counter, inputs=[], outputs=counter_display) |
| |
|
|
| if __name__ == "__main__": |
| print("Gradio version:", gr.__version__) |
| demo.launch(css=custom_css) |
|
|
|
|