Nhughes09 commited on
Commit
5a2e9d4
·
1 Parent(s): 77ed406

Working local Ollama chatbot with flexible history format and conversation memory

Browse files
Files changed (1) hide show
  1. app.py +102 -131
app.py CHANGED
@@ -1,4 +1,4 @@
1
- # app.py - Local Ollama Chatbot with DeepSeek
2
  import gradio as gr
3
  import requests
4
  import logging
@@ -7,170 +7,141 @@ import traceback
7
  from datetime import datetime
8
 
9
  # Logging
10
- logging.basicConfig(level=logging.INFO, format="%(asctime)s | %(message)s", handlers=[logging.StreamHandler(sys.stdout)])
 
 
 
 
11
  logger = logging.getLogger("CHATBOT")
 
 
12
 
13
  logger.info("=" * 60)
14
- logger.info(" DEEPSEEK CHATBOT - LOCAL OLLAMA")
15
  logger.info("=" * 60)
16
 
17
- # Config
18
  OLLAMA_URL = "http://localhost:11434"
19
- MODEL = "deepseek-coder:6.7b-instruct-q6_K"
20
 
21
- # Check connection
22
- ollama_connected = False
 
23
  try:
24
- resp = requests.get(f"{OLLAMA_URL}/api/tags", timeout=3)
25
- if resp.status_code == 200:
26
- models = [m["name"] for m in resp.json().get("models", [])]
 
27
  if MODEL in models:
28
- ollama_connected = True
29
- logger.info(f"Ollama connected! Using {MODEL}")
30
- else:
31
- logger.warning(f"Model {MODEL} not found. Available: {models}")
32
- except:
33
- logger.warning("Ollama not running")
34
-
35
- # Install instructions
36
- INSTALL_INSTRUCTIONS = """
37
- # 🚀 Local AI Chatbot Setup
38
-
39
- This chatbot runs on **YOUR computer** using Ollama + DeepSeek AI.
40
-
41
- ## Step 1: Install Ollama
42
-
43
- **Mac:**
44
- ```bash
45
- brew install ollama
46
- ```
47
-
48
- **Linux:**
49
- ```bash
50
- curl -fsSL https://ollama.com/install.sh | sh
51
- ```
52
-
53
- **Windows:** Download from [ollama.com/download](https://ollama.com/download)
54
-
55
- ---
56
-
57
- ## Step 2: Start Ollama & Download Model
58
-
59
- ```bash
60
- # Start Ollama (run in terminal, keep open)
61
- ollama serve
62
-
63
- # Download DeepSeek model (6.7GB, one-time)
64
- ollama pull deepseek-coder:6.7b-instruct-q6_K
65
- ```
66
-
67
- ---
68
-
69
- ## Step 3: Refresh This Page
70
-
71
- Once Ollama is running with the model, **refresh this page** and the chat will work!
72
-
73
- ---
74
-
75
- ### Alternative: Clone & Run Locally
76
-
77
- ```bash
78
- git clone https://huggingface.co/spaces/ndwdgda/cpu
79
- cd cpu
80
- pip install gradio requests
81
- python app.py
82
- ```
83
-
84
- Then open http://127.0.0.1:7860
85
- """
86
 
87
- # Chat function
88
  request_count = 0
89
 
90
- def chat_with_ai(message, history):
91
  global request_count
92
  request_count += 1
93
- rid = f"REQ-{request_count:04d}"
94
 
95
- logger.info(f"[{rid}] User: {message}")
 
 
96
 
97
- if not ollama_connected:
98
- return "Ollama not connected! See the Setup tab for instructions."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
 
100
  try:
101
- prompt = "You are a helpful AI coding assistant.\n\n"
102
- if history:
103
- for item in history:
104
- if isinstance(item, dict):
105
- r = item.get("role", "")
106
- c = str(item.get("content", ""))
107
- if r == "user":
108
- prompt += f"User: {c}\n"
109
- elif r == "assistant":
110
- prompt += f"Assistant: {c}\n"
111
- elif isinstance(item, (list, tuple)) and len(item) >= 2:
112
- prompt += f"User: {item[0]}\n"
113
- if item[1]:
114
- prompt += f"Assistant: {item[1]}\n"
115
-
116
- prompt += f"User: {message}\nAssistant:"
117
-
118
- logger.info(f"[{rid}] Calling DeepSeek...")
119
  start = datetime.now()
120
-
121
- resp = requests.post(
122
  f"{OLLAMA_URL}/api/generate",
123
  json={"model": MODEL, "prompt": prompt, "stream": False},
124
  timeout=120
125
  )
126
-
127
  elapsed = (datetime.now() - start).total_seconds()
128
 
129
- if resp.status_code == 200:
130
- result = resp.json()
131
- text = result.get("response", "")
132
- logger.info(f"[{rid}] Response in {elapsed:.1f}s: {text[:100]}...")
133
- return text.strip()
 
134
  else:
135
- return f"Error: {resp.status_code} - {resp.text[:200]}"
136
-
 
 
137
  except Exception as e:
138
- logger.error(f"[{rid}] Error: {e}")
139
  return f"Error: {e}"
140
 
141
  # UI
142
  logger.info("Building UI...")
143
 
144
- with gr.Blocks(theme=gr.themes.Soft()) as demo:
145
- gr.Markdown("# 🤖 DeepSeek AI Chatbot")
 
 
146
 
147
- if ollama_connected:
148
- gr.Markdown(f"**✅ Connected to Ollama** | Model: `{MODEL}`")
149
- else:
150
- gr.Markdown("**❌ Ollama not connected** - See **Setup** tab below for instructions!")
151
-
152
- with gr.Tabs():
153
- with gr.TabItem("💬 Chat"):
154
- chatbot = gr.Chatbot(height=400)
155
- msg = gr.Textbox(placeholder="Ask me anything..." if ollama_connected else "Install Ollama first (see Setup tab)", label="Message")
156
- with gr.Row():
157
- send = gr.Button("Send", variant="primary")
158
- clear = gr.ClearButton([msg, chatbot])
159
-
160
- def respond(message, history):
161
- if not message.strip():
162
- return "", history
163
- bot_response = chat_with_ai(message, history)
164
- history = history + [[message, bot_response]]
165
- return "", history
166
-
167
- msg.submit(respond, [msg, chatbot], [msg, chatbot])
168
- send.click(respond, [msg, chatbot], [msg, chatbot])
169
-
170
- with gr.TabItem("📋 Setup"):
171
- gr.Markdown(INSTALL_INSTRUCTIONS)
172
 
173
- logger.info("READY!")
174
 
175
  if __name__ == "__main__":
176
  demo.launch()
 
1
+ # app.py - Llama 3.2 Chatbot with Ollama
2
  import gradio as gr
3
  import requests
4
  import logging
 
7
  from datetime import datetime
8
 
9
  # Logging
10
+ logging.basicConfig(
11
+ level=logging.INFO,
12
+ format="%(asctime)s | %(levelname)-8s | %(message)s",
13
+ handlers=[logging.StreamHandler(sys.stdout)]
14
+ )
15
  logger = logging.getLogger("CHATBOT")
16
+ logging.getLogger("httpx").setLevel(logging.WARNING)
17
+ logging.getLogger("httpcore").setLevel(logging.WARNING)
18
 
19
  logger.info("=" * 60)
20
+ logger.info(" LLAMA 3.2 CHATBOT")
21
  logger.info("=" * 60)
22
 
 
23
  OLLAMA_URL = "http://localhost:11434"
24
+ MODEL = "llama3.2:3b"
25
 
26
+ # Check Ollama
27
+ logger.info(f"Checking Ollama...")
28
+ ollama_ok = False
29
  try:
30
+ r = requests.get(f"{OLLAMA_URL}/api/tags", timeout=5)
31
+ if r.status_code == 200:
32
+ models = [m["name"] for m in r.json().get("models", [])]
33
+ logger.info(f"Models: {models}")
34
  if MODEL in models:
35
+ ollama_ok = True
36
+ logger.info(f"CONNECTED - {MODEL}")
37
+ except Exception as e:
38
+ logger.error(f"Connection failed: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
 
40
+ # Chat function - FLEXIBLE history handling
41
  request_count = 0
42
 
43
+ def chat_fn(message, history):
44
  global request_count
45
  request_count += 1
46
+ rid = f"R{request_count:04d}"
47
 
48
+ logger.info(f"[{rid}] User: {message[:60]}...")
49
+ logger.info(f"[{rid}] History: {len(history)} items")
50
+ logger.info(f"[{rid}] History type: {type(history)}")
51
 
52
+ if not ollama_ok:
53
+ return "Ollama not connected. Install Ollama and run: ollama serve"
54
+
55
+ # Build prompt - HANDLE ANY HISTORY FORMAT
56
+ prompt = "You are a helpful AI assistant.\n\n"
57
+
58
+ try:
59
+ for i, item in enumerate(history):
60
+ logger.debug(f"[{rid}] History[{i}]: type={type(item)}, value={item}")
61
+
62
+ if isinstance(item, dict):
63
+ # Gradio 6.x format: {"role": "user", "content": "..."}
64
+ role = item.get("role", "")
65
+ content = str(item.get("content", ""))
66
+ if role == "user":
67
+ prompt += f"User: {content}\n"
68
+ elif role == "assistant":
69
+ prompt += f"Assistant: {content}\n"
70
+
71
+ elif isinstance(item, (list, tuple)):
72
+ # Old format: (user_msg, bot_msg) or [user_msg, bot_msg]
73
+ if len(item) == 2:
74
+ user_msg, bot_msg = item[0], item[1]
75
+ prompt += f"User: {user_msg}\n"
76
+ if bot_msg:
77
+ prompt += f"Assistant: {bot_msg}\n"
78
+ elif len(item) > 2:
79
+ # Handle unexpected tuple/list length
80
+ logger.warning(f"[{rid}] Unexpected item length: {len(item)}")
81
+ for j, sub in enumerate(item):
82
+ if isinstance(sub, dict):
83
+ role = sub.get("role", "")
84
+ content = str(sub.get("content", ""))
85
+ if role == "user":
86
+ prompt += f"User: {content}\n"
87
+ elif role == "assistant":
88
+ prompt += f"Assistant: {content}\n"
89
+ else:
90
+ logger.warning(f"[{rid}] Unknown history item type: {type(item)}")
91
+
92
+ except Exception as e:
93
+ logger.error(f"[{rid}] History parsing error: {e}")
94
+ logger.error(traceback.format_exc())
95
+
96
+ prompt += f"User: {message}\nAssistant:"
97
+
98
+ logger.info(f"[{rid}] Prompt: {len(prompt)} chars")
99
 
100
  try:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  start = datetime.now()
102
+ r = requests.post(
 
103
  f"{OLLAMA_URL}/api/generate",
104
  json={"model": MODEL, "prompt": prompt, "stream": False},
105
  timeout=120
106
  )
 
107
  elapsed = (datetime.now() - start).total_seconds()
108
 
109
+ logger.info(f"[{rid}] Status: {r.status_code}, Time: {elapsed:.1f}s")
110
+
111
+ if r.status_code == 200:
112
+ text = r.json().get("response", "").strip()
113
+ logger.info(f"[{rid}] Response: {text[:80]}...")
114
+ return text
115
  else:
116
+ return f"Error: Ollama returned {r.status_code}"
117
+ except requests.exceptions.Timeout:
118
+ logger.error(f"[{rid}] Timeout!")
119
+ return "Error: Request timed out (120s)"
120
  except Exception as e:
121
+ logger.error(f"[{rid}] Error: {e}\n{traceback.format_exc()}")
122
  return f"Error: {e}"
123
 
124
  # UI
125
  logger.info("Building UI...")
126
 
127
+ if ollama_ok:
128
+ description = f"**Connected** to Ollama | Model: `{MODEL}`"
129
+ else:
130
+ description = """**Not connected** - Install Ollama first:
131
 
132
+ **Mac:** `brew install ollama`
133
+ **Linux:** `curl -fsSL https://ollama.com/install.sh | sh`
134
+ **Then run:** `ollama serve` and `ollama pull llama3.2:3b`
135
+ """
136
+
137
+ demo = gr.ChatInterface(
138
+ fn=chat_fn,
139
+ title="Llama 3.2 Chatbot",
140
+ description=description,
141
+ examples=["Hello!", "What is Python?", "Tell me a joke"],
142
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
 
144
+ logger.info("READY! Open http://127.0.0.1:7860")
145
 
146
  if __name__ == "__main__":
147
  demo.launch()