File size: 5,287 Bytes
ab9f256
 
49fdf65
43b6f2d
 
36e65c3
f0f3c20
53e210f
49fdf65
5803d08
49fdf65
83facd4
5803d08
9a3b5e8
f0f3c20
 
 
 
 
49fdf65
8e173cc
5803d08
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8e173cc
 
 
 
5803d08
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8e173cc
49fdf65
5803d08
8e173cc
 
 
 
 
 
 
ab9f256
 
43b6f2d
 
8e173cc
43b6f2d
 
8e173cc
43b6f2d
 
8e173cc
43b6f2d
8e173cc
5803d08
43b6f2d
ab9f256
8e173cc
5803d08
 
 
 
8e173cc
f0f3c20
8e173cc
5803d08
49fdf65
8e173cc
ab9f256
49fdf65
5803d08
49fdf65
5803d08
 
 
8e173cc
 
5803d08
 
 
8e173cc
 
5803d08
8e173cc
5803d08
8e173cc
5803d08
 
 
 
 
 
8e173cc
5803d08
 
 
 
 
8e173cc
43b6f2d
8e173cc
 
5803d08
8e173cc
43b6f2d
8e173cc
5803d08
8e173cc
5803d08
8e173cc
 
 
ab9f256
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import gradio as gr
import os
import json
from Pdf_utils import extract_text_from_pdf
from ocr_utils import extract_text_from_image
from Prompt_Builder import build_prompt
from openai import OpenAI

# ----------------------------
# CONFIG & SECRETS
# ----------------------------
GROQ_API_KEY = os.environ.get("GROQ_API_KEY")
OCR_API_KEY = os.environ.get("OCR_API_KEY")

client = OpenAI(
    api_key=GROQ_API_KEY,
    base_url="https://api.groq.com/openai/v1",
)

# ----------------------------
# UI CUSTOMIZATION (Vanta.js + Glassmorphism)
# ----------------------------
css = """
footer {visibility: hidden}
.gradio-container {
    background: rgba(10, 25, 47, 0.7) !important;
    backdrop-filter: blur(15px) !important;
    border: 1px solid rgba(255, 255, 255, 0.1) !important;
    border-radius: 20px !important;
    color: white !important;
}
#vanta-canvas {
    position: fixed;
    top: 0; left: 0; width: 100vw; height: 100vh;
    z-index: -1;
}
#output-box {
    background: rgba(0, 0, 0, 0.3) !important;
    padding: 20px;
    border-radius: 10px;
}
"""

vanta_head = """
<div id="vanta-canvas"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r134/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vanta@latest/dist/vanta.net.min.js"></script>
<script>
    document.addEventListener('DOMContentLoaded', function() {
        VANTA.NET({
          el: "#vanta-canvas",
          mouseControls: true,
          touchControls: true,
          gyroControls: false,
          minHeight: 200.00,
          minWidth: 200.00,
          scale: 1.00,
          scaleMobile: 1.00,
          color: 0x3fbbee,
          backgroundColor: 0x0a192f,
          points: 15.00,
          maxDistance: 20.00,
          spacing: 16.00
        })
    });
</script>
"""

# ----------------------------
# CORE LOGIC WITH UX ALERTS
# ----------------------------
def generate_nexus_post(file, user_text, url, url_desc, hashtags, custom_p, suggestions, model_name):
    # Validation Check
    if not file and not user_text.strip():
        raise gr.Error("Bhai, kam az kam kuch text ya file toh do! Input empty hai.")

    # User Feedback Notification
    gr.Info("🚀 Processing your request... Sit tight!")
    
    file_text = ""
    if file:
        try:
            if file.name.lower().endswith(".pdf"):
                gr.Info("📄 Reading PDF...")
                file_text = extract_text_from_pdf(file.name)
            else:
                gr.Info("🖼️ Running OCR on Image...")
                file_text = extract_text_from_image(file.name, OCR_API_KEY)
        except Exception as e:
            raise gr.Error(f"File processing error: {str(e)}")

    # Prompt Building
    final_prompt = build_prompt(user_text, file_text, {"url": url, "description": url_desc}, [], hashtags.split(","), custom_p, suggestions)

    try:
        gr.Info("🤖 AI is ghostwriting your post...")
        completion = client.chat.completions.create(
            model=model_name,
            messages=[{"role": "user", "content": final_prompt}],
            temperature=0.7,
            timeout=45.0 # Pre-emptively stop if API is stuck
        )
        gr.Info("✅ Done! Post generated.")
        return completion.choices[0].message.content
    except Exception as e:
        raise gr.Error(f"API Error: {str(e)}")

# ----------------------------
# GRADIO INTERFACE
# ----------------------------
with gr.Blocks(theme=gr.themes.Default(), css=css) as demo:
    gr.HTML(vanta_head)
    
    with gr.Column():
        gr.Markdown("# 🚀 Nexus Post AI\n### Professional LinkedIn Ghostwriter")
        
        with gr.Row():
            with gr.Column(scale=1):
                file_input = gr.File(label="Upload Context (PDF/Image)")
                user_msg = gr.Textbox(label="Core Idea", placeholder="What's this post about?", lines=3)
                
                with gr.Accordion("🔗 Links & Tags", open=False):
                    link_url = gr.Textbox(label="Reference URL")
                    link_d = gr.Textbox(label="Link Description")
                    tags = gr.Textbox(label="Hashtags (comma separated)")
            
            with gr.Column(scale=1):
                model_drop = gr.Dropdown(
                    choices=["llama-3.3-70b-versatile", "mixtral-8x7b-32768"],
                    value="llama-3.3-70b-versatile",
                    label="AI Model"
                )
                ai_adds = gr.CheckboxGroup(
                    label="Enhancements",
                    choices=["Strong Hook", "Storytelling", "Bullet Points", "Emojis", "Call-to-Action"]
                )
                custom_inst = gr.Textbox(label="Custom Instructions", placeholder="e.g. 'Make it professional'")

        # Button with explicit loading
        submit_btn = gr.Button("🔥 GENERATE POST", variant="primary")
        
        output_display = gr.Markdown(label="Generated Drafts", elem_id="output-box")

    # The Logic Trigger
    submit_btn.click(
        fn=generate_nexus_post,
        inputs=[file_input, user_msg, link_url, link_d, tags, custom_inst, ai_adds, model_drop],
        outputs=output_display,
        show_progress="full", # Full screen overlay for clear status
        scroll_to_output=True
    )

demo.launch()