Kiki0203 commited on
Commit
7f45575
Β·
verified Β·
1 Parent(s): 6898c37

Upload 3 files

Browse files
Files changed (3) hide show
  1. README.md +81 -5
  2. app.py +334 -0
  3. requirements.txt +4 -0
README.md CHANGED
@@ -1,12 +1,88 @@
1
  ---
2
- title: LangGraph Chatbot
3
- emoji: 🌍
4
  colorFrom: indigo
5
- colorTo: red
6
  sdk: gradio
7
- sdk_version: 6.11.0
8
  app_file: app.py
9
  pinned: false
 
 
10
  ---
11
 
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: AI Assistant β€” LangGraph + Groq
3
+ emoji: ⚑
4
  colorFrom: indigo
5
+ colorTo: purple
6
  sdk: gradio
7
+ sdk_version: "4.44.0"
8
  app_file: app.py
9
  pinned: false
10
+ license: mit
11
+ short_description: General-purpose AI chatbot built with LangGraph and Groq
12
  ---
13
 
14
+ # ⚑ AI Assistant β€” LangGraph + Groq
15
+
16
+ A sleek, production-ready general-purpose chatbot built with:
17
+
18
+ - 🧠 **[LangGraph](https://github.com/langchain-ai/langgraph)** β€” stateful agent graph for conversation flow
19
+ - ⚑ **[Groq](https://groq.com/)** β€” blazing-fast LLM inference (llama-3.3-70b-versatile)
20
+ - 🎨 **[Gradio](https://gradio.app/)** β€” beautiful, interactive UI
21
+
22
+ ---
23
+
24
+ ## πŸš€ Setup
25
+
26
+ ### Run locally
27
+
28
+ ```bash
29
+ git clone https://huggingface.co/spaces/YOUR_USERNAME/YOUR_SPACE_NAME
30
+ cd YOUR_SPACE_NAME
31
+ pip install -r requirements.txt
32
+ export GROQ_API_KEY=your_key_here
33
+ python app.py
34
+ ```
35
+
36
+ ### Deploy on Hugging Face Spaces
37
+
38
+ 1. Create a new Space on [huggingface.co/spaces](https://huggingface.co/spaces) (SDK: Gradio)
39
+ 2. Push this repo to that Space
40
+ 3. Go to **Settings β†’ Variables and Secrets** β†’ add `GROQ_API_KEY`
41
+ 4. Your Space will build and launch automatically βœ…
42
+
43
+ ---
44
+
45
+ ## πŸ”‘ API Key
46
+
47
+ Get your free Groq API key at [console.groq.com](https://console.groq.com).
48
+
49
+ ---
50
+
51
+ ## πŸ—‚ Project Structure
52
+
53
+ ```
54
+ β”œβ”€β”€ app.py # Main app β€” LangGraph graph + Gradio UI
55
+ β”œβ”€β”€ requirements.txt # Dependencies
56
+ └── README.md # This file
57
+ ```
58
+
59
+ ---
60
+
61
+ ## 🧩 How it works
62
+
63
+ ```
64
+ User message
65
+ β”‚
66
+ β–Ό
67
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
68
+ β”‚ Gradio UI β”‚ ← Converts chat history to LangChain messages
69
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
70
+ β”‚
71
+ β–Ό
72
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
73
+ β”‚ LangGraph β”‚ ← StateGraph with a single `chatbot` node
74
+ β”‚ StateGraph β”‚
75
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
76
+ β”‚
77
+ β–Ό
78
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
79
+ β”‚ Groq LLM β”‚ ← llama-3.3-70b-versatile (fast & smart)
80
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
81
+ β”‚
82
+ β–Ό
83
+ AI Response
84
+ ```
85
+
86
+ ---
87
+
88
+ Built with ❀️ using LangGraph + Groq + Gradio
app.py ADDED
@@ -0,0 +1,334 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import gradio as gr
3
+ from typing import Annotated
4
+ from typing_extensions import TypedDict
5
+ from langgraph.graph import StateGraph, START, END
6
+ from langgraph.graph.message import add_messages
7
+ from langchain_groq import ChatGroq
8
+ from langchain_core.messages import HumanMessage, AIMessage, SystemMessage
9
+
10
+ # ── State ────────────────────────────────────────────────────────────────────
11
+
12
+ class State(TypedDict):
13
+ messages: Annotated[list, add_messages]
14
+
15
+ # ── LLM & Graph ──────────────────────────────────────────────────────────────
16
+
17
+ SYSTEM_PROMPT = """You are a brilliant, friendly, and concise general-purpose AI assistant.
18
+ You help users with anything they ask β€” questions, writing, analysis, coding, brainstorming, and more.
19
+ Be warm, clear, and genuinely helpful. When you don't know something, say so honestly."""
20
+
21
+ def get_llm():
22
+ """Return the best available Groq model."""
23
+ api_key = os.environ.get("GROQ_API_KEY", "")
24
+ # Try models in order of preference
25
+ for model in [
26
+ "llama-3.3-70b-versatile",
27
+ "llama-3.1-70b-versatile",
28
+ "mixtral-8x7b-32768",
29
+ "llama-3.1-8b-instant",
30
+ ]:
31
+ try:
32
+ llm = ChatGroq(model=model, api_key=api_key, temperature=0.7)
33
+ return llm, model
34
+ except Exception:
35
+ continue
36
+ raise RuntimeError("No Groq model available. Check your GROQ_API_KEY.")
37
+
38
+ llm, active_model = get_llm()
39
+
40
+ def chatbot_node(state: State):
41
+ """Core LangGraph node: calls the LLM with full message history."""
42
+ messages = [SystemMessage(content=SYSTEM_PROMPT)] + state["messages"]
43
+ response = llm.invoke(messages)
44
+ return {"messages": [response]}
45
+
46
+ def build_graph():
47
+ builder = StateGraph(State)
48
+ builder.add_node("chatbot", chatbot_node)
49
+ builder.add_edge(START, "chatbot")
50
+ builder.add_edge("chatbot", END)
51
+ return builder.compile()
52
+
53
+ graph = build_graph()
54
+
55
+ # ── Chat logic ────────────────────────────────────────────────────────────────
56
+
57
+ def chat(user_message: str, history: list):
58
+ """Convert Gradio history β†’ LangChain messages β†’ run graph β†’ return reply."""
59
+ if not user_message.strip():
60
+ return "", history
61
+
62
+ # Build message list from history
63
+ lc_messages = []
64
+ for human, assistant in history:
65
+ lc_messages.append(HumanMessage(content=human))
66
+ if assistant:
67
+ lc_messages.append(AIMessage(content=assistant))
68
+ lc_messages.append(HumanMessage(content=user_message))
69
+
70
+ # Run through LangGraph
71
+ result = graph.invoke({"messages": lc_messages})
72
+ ai_reply = result["messages"][-1].content
73
+
74
+ history.append((user_message, ai_reply))
75
+ return "", history
76
+
77
+ def clear_chat():
78
+ return [], []
79
+
80
+ # ── Gradio UI ─────────────────────────────────────────────────────────────────
81
+
82
+ CSS = """
83
+ @import url('https://fonts.googleapis.com/css2?family=Syne:wght@400;600;700;800&family=DM+Sans:ital,wght@0,300;0,400;0,500;1,300&display=swap');
84
+
85
+ :root {
86
+ --bg-primary: #0a0a0f;
87
+ --bg-card: #111118;
88
+ --bg-input: #1a1a24;
89
+ --border: #2a2a3a;
90
+ --accent: #7c6af7;
91
+ --accent-soft: #9d91f8;
92
+ --accent-glow: rgba(124, 106, 247, 0.15);
93
+ --text-primary: #f0eff8;
94
+ --text-muted: #7a798a;
95
+ --user-bubble: linear-gradient(135deg, #7c6af7, #5b4fd4);
96
+ --bot-bubble: #1a1a24;
97
+ --success: #4ade80;
98
+ --radius: 16px;
99
+ }
100
+
101
+ * { box-sizing: border-box; }
102
+
103
+ body, .gradio-container {
104
+ background: var(--bg-primary) !important;
105
+ font-family: 'DM Sans', sans-serif !important;
106
+ color: var(--text-primary) !important;
107
+ }
108
+
109
+ .gradio-container {
110
+ max-width: 860px !important;
111
+ margin: 0 auto !important;
112
+ padding: 0 !important;
113
+ }
114
+
115
+ /* Header */
116
+ #header {
117
+ text-align: center;
118
+ padding: 48px 32px 24px;
119
+ position: relative;
120
+ }
121
+
122
+ #header::before {
123
+ content: '';
124
+ position: absolute;
125
+ top: 0; left: 50%;
126
+ transform: translateX(-50%);
127
+ width: 300px; height: 200px;
128
+ background: radial-gradient(ellipse, rgba(124,106,247,0.18) 0%, transparent 70%);
129
+ pointer-events: none;
130
+ }
131
+
132
+ #app-title {
133
+ font-family: 'Syne', sans-serif !important;
134
+ font-size: 2.6rem !important;
135
+ font-weight: 800 !important;
136
+ letter-spacing: -0.03em !important;
137
+ background: linear-gradient(135deg, #f0eff8 30%, #9d91f8) !important;
138
+ -webkit-background-clip: text !important;
139
+ -webkit-text-fill-color: transparent !important;
140
+ background-clip: text !important;
141
+ margin: 0 0 8px !important;
142
+ line-height: 1.1 !important;
143
+ }
144
+
145
+ #app-subtitle {
146
+ color: var(--text-muted) !important;
147
+ font-size: 1rem !important;
148
+ font-weight: 300 !important;
149
+ margin: 0 !important;
150
+ }
151
+
152
+ /* Model badge */
153
+ #model-badge {
154
+ display: inline-flex;
155
+ align-items: center;
156
+ gap: 6px;
157
+ background: var(--accent-glow);
158
+ border: 1px solid rgba(124,106,247,0.3);
159
+ border-radius: 100px;
160
+ padding: 4px 14px;
161
+ margin-top: 14px;
162
+ font-size: 0.78rem;
163
+ color: var(--accent-soft);
164
+ font-family: 'DM Sans', monospace;
165
+ }
166
+
167
+ /* Chat area */
168
+ #chatbot-box {
169
+ background: var(--bg-card) !important;
170
+ border: 1px solid var(--border) !important;
171
+ border-radius: var(--radius) !important;
172
+ margin: 0 24px !important;
173
+ overflow: hidden !important;
174
+ }
175
+
176
+ #chatbot-box .wrap {
177
+ background: transparent !important;
178
+ padding: 16px !important;
179
+ }
180
+
181
+ /* Messages */
182
+ .message {
183
+ border-radius: 14px !important;
184
+ padding: 14px 18px !important;
185
+ font-size: 0.97rem !important;
186
+ line-height: 1.65 !important;
187
+ max-width: 82% !important;
188
+ margin-bottom: 4px !important;
189
+ }
190
+
191
+ .message.user {
192
+ background: var(--user-bubble) !important;
193
+ color: #fff !important;
194
+ margin-left: auto !important;
195
+ box-shadow: 0 4px 20px rgba(124,106,247,0.3) !important;
196
+ }
197
+
198
+ .message.bot {
199
+ background: var(--bot-bubble) !important;
200
+ color: var(--text-primary) !important;
201
+ border: 1px solid var(--border) !important;
202
+ }
203
+
204
+ /* Input row */
205
+ #input-row {
206
+ display: flex;
207
+ gap: 10px;
208
+ padding: 16px 24px 12px !important;
209
+ align-items: flex-end;
210
+ }
211
+
212
+ #msg-input textarea {
213
+ background: var(--bg-input) !important;
214
+ border: 1px solid var(--border) !important;
215
+ border-radius: 12px !important;
216
+ color: var(--text-primary) !important;
217
+ font-family: 'DM Sans', sans-serif !important;
218
+ font-size: 0.97rem !important;
219
+ padding: 14px 16px !important;
220
+ resize: none !important;
221
+ transition: border-color 0.2s !important;
222
+ }
223
+
224
+ #msg-input textarea:focus {
225
+ border-color: var(--accent) !important;
226
+ outline: none !important;
227
+ box-shadow: 0 0 0 3px var(--accent-glow) !important;
228
+ }
229
+
230
+ #msg-input textarea::placeholder { color: var(--text-muted) !important; }
231
+
232
+ #msg-input label { display: none !important; }
233
+
234
+ /* Buttons */
235
+ #send-btn, #clear-btn {
236
+ border-radius: 12px !important;
237
+ font-family: 'Syne', sans-serif !important;
238
+ font-weight: 600 !important;
239
+ font-size: 0.9rem !important;
240
+ padding: 0 22px !important;
241
+ height: 50px !important;
242
+ transition: all 0.2s !important;
243
+ cursor: pointer !important;
244
+ white-space: nowrap !important;
245
+ }
246
+
247
+ #send-btn {
248
+ background: linear-gradient(135deg, #7c6af7, #5b4fd4) !important;
249
+ color: #fff !important;
250
+ border: none !important;
251
+ box-shadow: 0 4px 16px rgba(124,106,247,0.35) !important;
252
+ }
253
+
254
+ #send-btn:hover {
255
+ transform: translateY(-1px) !important;
256
+ box-shadow: 0 6px 22px rgba(124,106,247,0.5) !important;
257
+ }
258
+
259
+ #clear-btn {
260
+ background: transparent !important;
261
+ color: var(--text-muted) !important;
262
+ border: 1px solid var(--border) !important;
263
+ }
264
+
265
+ #clear-btn:hover {
266
+ border-color: #ff6b6b !important;
267
+ color: #ff6b6b !important;
268
+ background: rgba(255,107,107,0.07) !important;
269
+ }
270
+
271
+ /* Footer */
272
+ #footer {
273
+ text-align: center;
274
+ padding: 16px 24px 32px;
275
+ color: var(--text-muted);
276
+ font-size: 0.78rem;
277
+ }
278
+
279
+ /* Scrollbar */
280
+ ::-webkit-scrollbar { width: 5px; }
281
+ ::-webkit-scrollbar-track { background: transparent; }
282
+ ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 10px; }
283
+ """
284
+
285
+ with gr.Blocks(css=CSS, title="AI Assistant", theme=gr.themes.Base()) as demo:
286
+
287
+ # ── Header ──────────────────────────────────────────────────────────────
288
+ with gr.Column(elem_id="header"):
289
+ gr.HTML(f"""
290
+ <h1 id="app-title">AI Assistant</h1>
291
+ <p id="app-subtitle">Powered by LangGraph &amp; Groq β€” fast, smart, always on.</p>
292
+ <div id="model-badge">
293
+ ⚑ {active_model}
294
+ </div>
295
+ """)
296
+
297
+ # ── Chat window ──────────────────────────────────────────────────────────
298
+ chatbot = gr.Chatbot(
299
+ value=[],
300
+ elem_id="chatbot-box",
301
+ label="",
302
+ height=460,
303
+ bubble_full_width=False,
304
+ show_label=False,
305
+ avatar_images=(None, "https://api.dicebear.com/7.x/bottts-neutral/svg?seed=langgraph&backgroundColor=7c6af7"),
306
+ )
307
+
308
+ # ── Input row ────────────────────────────────────────────────────────────
309
+ with gr.Row(elem_id="input-row"):
310
+ msg = gr.Textbox(
311
+ placeholder="Ask me anything…",
312
+ show_label=False,
313
+ lines=1,
314
+ max_lines=5,
315
+ elem_id="msg-input",
316
+ scale=8,
317
+ )
318
+ send_btn = gr.Button("Send ↑", elem_id="send-btn", scale=1)
319
+ clear_btn = gr.Button("Clear", elem_id="clear-btn", scale=1)
320
+
321
+ # ── Footer ───────────────────────────────────────────────────────────────
322
+ gr.HTML("""
323
+ <div id="footer">
324
+ Built with LangGraph Β· Groq Β· Gradio &nbsp;|&nbsp; Deploy on πŸ€— Hugging Face Spaces
325
+ </div>
326
+ """)
327
+
328
+ # ── Events ───────────────────────────────────────────────────────────────
329
+ send_btn.click(chat, [msg, chatbot], [msg, chatbot])
330
+ msg.submit(chat, [msg, chatbot], [msg, chatbot])
331
+ clear_btn.click(clear_chat, outputs=[msg, chatbot])
332
+
333
+ if __name__ == "__main__":
334
+ demo.launch(server_name="0.0.0.0", server_port=7860)
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ gradio>=4.44.0
2
+ langgraph>=0.2.0
3
+ langchain-groq>=0.2.0
4
+ langchain-core>=0.3.0