bahadur3093 commited on
Commit
8d8e945
·
1 Parent(s): 63e82f2

feat: Add environment-based configuration and chat history support

Browse files
.env.example ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ollama Configuration
2
+ # For local development, use localhost
3
+ # OLLAMA_BASE_URL=http://localhost:11434
4
+
5
+ # For Hugging Face Space deployment
6
+ # Replace with your actual Ollama server endpoint
7
+ # If hosting on Hugging Face Spaces, use your Space URL:
8
+ # OLLAMA_BASE_URL=https://huggingface.co/spaces/YOUR_USERNAME/YOUR_SPACE_NAME
9
+ OLLAMA_BASE_URL=https://huggingface.co/spaces/bahadur3093/ollama-server
10
+
11
+ # Environment (development, production)
12
+ NODE_ENV=production
.gitignore CHANGED
@@ -28,9 +28,11 @@ yarn-error.log*
28
  # local env files
29
  .env*.local
30
  .env
 
31
  .env.development.local
32
  .env.test.local
33
  .env.production.local
 
34
 
35
  # vercel
36
  .vercel
 
28
  # local env files
29
  .env*.local
30
  .env
31
+ .env.local
32
  .env.development.local
33
  .env.test.local
34
  .env.production.local
35
+ !.env.example
36
 
37
  # vercel
38
  .vercel
HUGGINGFACE_DEPLOYMENT.md ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Hugging Face Spaces Deployment Guide
2
+
3
+ ## Your Space Information
4
+ - **Space URL**: https://huggingface.co/spaces/bahadur3093/ollama-server
5
+ - **Space Type**: Gradio App
6
+
7
+ ## Environment Configuration for Hugging Face Spaces
8
+
9
+ ### Setting Up Environment Variables (Secrets)
10
+
11
+ Since your Space is hosted on Hugging Face, you need to configure the `OLLAMA_BASE_URL` as a **Space Secret**:
12
+
13
+ 1. **Go to your Space Settings**:
14
+ - Navigate to: https://huggingface.co/spaces/bahadur3093/ollama-server/settings
15
+
16
+ 2. **Add Repository Secret**:
17
+ - Scroll to the "Repository secrets" section
18
+ - Click "New secret"
19
+ - Name: `OLLAMA_BASE_URL`
20
+ - Value: Your actual Ollama server URL (see options below)
21
+
22
+ ### Ollama Server Options for Hugging Face Deployment
23
+
24
+ #### Option 1: External Ollama Server (Recommended)
25
+ If you have an Ollama server running elsewhere:
26
+ ```
27
+ OLLAMA_BASE_URL=https://your-ollama-server.com
28
+ ```
29
+
30
+ #### Option 2: Self-Hosted Ollama API
31
+ If you're running Ollama on a VPS or cloud instance:
32
+ ```
33
+ OLLAMA_BASE_URL=http://your-server-ip:11434
34
+ ```
35
+
36
+ #### Option 3: Hugging Face Inference API
37
+ If you want to use Hugging Face's inference endpoints:
38
+ ```
39
+ OLLAMA_BASE_URL=https://api-inference.huggingface.co/models
40
+ ```
41
+ (Note: This requires adapting the API format)
42
+
43
+ #### Option 4: Local Testing
44
+ For local development (already configured in app.py):
45
+ ```
46
+ OLLAMA_BASE_URL=http://localhost:11434
47
+ ```
48
+
49
+ ## Committing Changes to Hugging Face
50
+
51
+ ### Important Files to Commit
52
+
53
+ ✅ **DO COMMIT**:
54
+ - `app.py` (updated with environment variable support)
55
+ - `requirements.txt`
56
+ - `README.md`
57
+ - `.gitignore`
58
+
59
+ ❌ **DO NOT COMMIT**:
60
+ - `.env.local` (contains local development settings)
61
+ - `.env` (if it exists)
62
+
63
+ These files are already excluded in `.gitignore`
64
+
65
+ ### Deployment Steps
66
+
67
+ 1. **Commit your changes**:
68
+ ```bash
69
+ git add app.py requirements.txt README.md .gitignore
70
+ git commit -m "Add environment-based Ollama URL configuration"
71
+ ```
72
+
73
+ 2. **Push to Hugging Face**:
74
+ ```bash
75
+ git push origin main
76
+ ```
77
+
78
+ 3. **Set the Secret** (if not already done):
79
+ - Go to Space Settings → Repository secrets
80
+ - Add `OLLAMA_BASE_URL` with your production Ollama server URL
81
+
82
+ 4. **Verify Deployment**:
83
+ - Your Space will automatically rebuild
84
+ - Check the UI - it should display "Connected to: [your-url]"
85
+ - Test with a prompt to ensure connectivity
86
+
87
+ ## Current Configuration
88
+
89
+ ### app.py Changes
90
+ - ✅ Reads `OLLAMA_BASE_URL` from environment variables
91
+ - ✅ Falls back to `http://localhost:11434` for local development
92
+ - ✅ Displays connected server URL in the UI
93
+ - ✅ Improved error handling with timeout and detailed error messages
94
+
95
+ ### Local Development Workflow
96
+
97
+ 1. **For local testing** (using localhost Ollama):
98
+ ```bash
99
+ # No environment variable needed - defaults to localhost:11434
100
+ python app.py
101
+ ```
102
+
103
+ 2. **For testing with remote Ollama**:
104
+ ```bash
105
+ export OLLAMA_BASE_URL=https://your-test-server.com
106
+ python app.py
107
+ ```
108
+
109
+ ## Troubleshooting
110
+
111
+ ### Issue: "Could not connect to Ollama server"
112
+ **Solution**:
113
+ - Verify `OLLAMA_BASE_URL` is set correctly in Space secrets
114
+ - Ensure your Ollama server is accessible from Hugging Face (public URL)
115
+ - Check firewall rules on your Ollama server
116
+
117
+ ### Issue: Space not updating after commit
118
+ **Solution**:
119
+ - Check the "Logs" tab in your Space
120
+ - Verify the build completed successfully
121
+ - Try a hard refresh (Ctrl+Shift+R)
122
+
123
+ ### Issue: Environment variable not working
124
+ **Solution**:
125
+ - Ensure the secret name is exactly `OLLAMA_BASE_URL` (case-sensitive)
126
+ - Restart your Space after adding secrets
127
+ - Check Space logs for any errors
128
+
129
+ ## Next Steps
130
+
131
+ 1. ✅ Set `OLLAMA_BASE_URL` in Hugging Face Space secrets
132
+ 2. ✅ Commit and push changes to Hugging Face
133
+ 3. ✅ Test the deployed Space
134
+ 4. ✅ Monitor logs for any connection issues
135
+
136
+ ## Notes
137
+
138
+ - The `.env.local` file is for **local development only** and should never be committed
139
+ - Hugging Face Spaces uses **repository secrets** for environment variables
140
+ - The app automatically switches between local and production URLs based on environment
141
+ - No special deployment configuration needed - just set the secret and push!
README_CONFIGURATION.md ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ollama Chat Configuration Guide
2
+
3
+ ## Overview
4
+ This application now supports conversation memory and environment-based configuration for switching between local Ollama (testing) and production Ollama servers.
5
+
6
+ ## What Was Fixed
7
+
8
+ ### 1. **Conversation Memory Issue**
9
+ The model wasn't remembering previous messages because:
10
+ - The app was using Ollama's `/api/generate` endpoint (stateless, single prompt)
11
+ - No conversation history was being passed to the model
12
+
13
+ **Solution:**
14
+ - Switched to Ollama's `/api/chat` endpoint
15
+ - Now reads chat history from `chat-history.json` and passes all previous messages to the model
16
+ - The model now maintains full conversation context
17
+
18
+ ### 2. **Environment-Based Configuration**
19
+ Added support for automatic switching between local and production Ollama servers.
20
+
21
+ ## Configuration
22
+
23
+ ### Environment Variables
24
+
25
+ Create a `.env.local` file in the root directory:
26
+
27
+ ```bash
28
+ # For local development (default)
29
+ OLLAMA_BASE_URL=http://localhost:11434
30
+ NODE_ENV=development
31
+
32
+ # For production deployment
33
+ # OLLAMA_BASE_URL=https://your-ollama-server.com
34
+ # NODE_ENV=production
35
+ ```
36
+
37
+ ### Automatic Switching
38
+
39
+ The application will automatically use:
40
+ - **Local Ollama** (`http://localhost:11434`) when `OLLAMA_BASE_URL` is not set
41
+ - **Production Ollama** when you set `OLLAMA_BASE_URL` to your deployed server
42
+
43
+ ### Deployment Setup
44
+
45
+ #### Option 1: Environment Variables (Recommended)
46
+ Set the `OLLAMA_BASE_URL` environment variable in your deployment platform:
47
+
48
+ **Vercel:**
49
+ ```bash
50
+ vercel env add OLLAMA_BASE_URL
51
+ # Enter: https://your-ollama-server.com
52
+ ```
53
+
54
+ **Docker:**
55
+ ```bash
56
+ docker run -e OLLAMA_BASE_URL=https://your-ollama-server.com ...
57
+ ```
58
+
59
+ **Railway/Render/Heroku:**
60
+ Add `OLLAMA_BASE_URL` in the environment variables section of your dashboard.
61
+
62
+ #### Option 2: Git-Based Switching
63
+ Create different `.env` files for different environments:
64
+
65
+ ```bash
66
+ # .env.development (for local)
67
+ OLLAMA_BASE_URL=http://localhost:11434
68
+
69
+ # .env.production (for deployment)
70
+ OLLAMA_BASE_URL=https://your-ollama-server.com
71
+ ```
72
+
73
+ Add to `.gitignore`:
74
+ ```
75
+ .env.local
76
+ .env*.local
77
+ ```
78
+
79
+ Commit only `.env.example` to git, and set up your CI/CD to copy the appropriate file during deployment.
80
+
81
+ ## Testing
82
+
83
+ ### Local Testing
84
+ 1. Make sure Ollama is running locally:
85
+ ```bash
86
+ ollama serve
87
+ ```
88
+
89
+ 2. Start the development server:
90
+ ```bash
91
+ npm run dev
92
+ ```
93
+
94
+ 3. The app will connect to `http://localhost:11434`
95
+
96
+ ### Production Testing
97
+ 1. Set `OLLAMA_BASE_URL` to your production server
98
+ 2. Build and deploy:
99
+ ```bash
100
+ npm run build
101
+ npm start
102
+ ```
103
+
104
+ ## How It Works
105
+
106
+ ### Conversation Flow
107
+ 1. User sends a message
108
+ 2. Message is saved to `chat-history.json`
109
+ 3. API reads all previous messages from history
110
+ 4. Sends complete conversation to Ollama's `/api/chat` endpoint
111
+ 5. Model responds with context from entire conversation
112
+ 6. Response is saved to history and displayed
113
+
114
+ ### API Endpoints Updated
115
+ - `pages/api/generate.ts` - Now uses chat API with history
116
+ - `pages/api/models.ts` - Uses environment-based URL
117
+ - `pages/api/pull.ts` - Uses environment-based URL
118
+
119
+ ### Configuration Files
120
+ - `next.config.js` - Exposes `OLLAMA_BASE_URL` to the app
121
+ - `.env.local` - Local environment configuration (not committed)
122
+ - `.env.example` - Template for environment variables (committed)
123
+
124
+ ## Troubleshooting
125
+
126
+ ### Model not remembering conversations
127
+ - Check that `chat-history.json` exists and contains messages
128
+ - Verify the API is using `/api/chat` endpoint (not `/api/generate`)
129
+ - Clear chat history and start a new conversation
130
+
131
+ ### Connection errors
132
+ - Verify `OLLAMA_BASE_URL` is set correctly
133
+ - Check that Ollama server is running and accessible
134
+ - Test the URL directly: `curl http://localhost:11434/api/tags`
135
+
136
+ ### Environment variable not working
137
+ - Restart the development server after changing `.env.local`
138
+ - Verify the variable is set: `console.log(process.env.OLLAMA_BASE_URL)`
139
+ - For production, ensure the platform has the environment variable set
140
+
141
+ ## Additional Notes
142
+
143
+ - The chat history is stored in `chat-history.json` in the project root
144
+ - Clearing chat history (🗑️ button) will reset the conversation context
145
+ - Each message includes metadata (timestamp, model used)
146
+ - The system automatically filters and formats messages for Ollama's API
app.py CHANGED
@@ -1,22 +1,30 @@
1
  import requests
2
  import gradio as gr
 
3
 
4
- OLLAMA_URL = "http://localhost:11434/api/generate"
 
 
 
 
5
 
6
  def generate_response(model, prompt):
7
- response = requests.post(
8
- OLLAMA_URL,
9
- json={
10
- "model": model,
11
- "prompt": prompt,
12
- "stream": False
13
- }
14
- )
15
-
16
  try:
 
 
 
 
 
 
 
 
 
 
17
  return response.json()["response"]
18
- except:
19
- return "Error: Could not get response"
 
 
20
 
21
  # 🔥 Available models (you can update this)
22
  models = [
@@ -28,7 +36,8 @@ models = [
28
 
29
  # UI
30
  with gr.Blocks() as app:
31
- gr.Markdown("# 🚀 Your Ollama UI")
 
32
 
33
  model_dropdown = gr.Dropdown(models, value="mistral", label="Select Model")
34
  prompt_input = gr.Textbox(lines=5, label="Enter Prompt")
 
1
  import requests
2
  import gradio as gr
3
+ import os
4
 
5
+ # Environment-based configuration
6
+ # For Hugging Face Spaces, set OLLAMA_BASE_URL in Space secrets
7
+ # For local development, it defaults to localhost
8
+ OLLAMA_BASE_URL = os.getenv("OLLAMA_BASE_URL", "http://localhost:11434")
9
+ OLLAMA_URL = f"{OLLAMA_BASE_URL}/api/generate"
10
 
11
  def generate_response(model, prompt):
 
 
 
 
 
 
 
 
 
12
  try:
13
+ response = requests.post(
14
+ OLLAMA_URL,
15
+ json={
16
+ "model": model,
17
+ "prompt": prompt,
18
+ "stream": False
19
+ },
20
+ timeout=30
21
+ )
22
+ response.raise_for_status()
23
  return response.json()["response"]
24
+ except requests.exceptions.RequestException as e:
25
+ return f"Error: Could not connect to Ollama server at {OLLAMA_BASE_URL}. Details: {str(e)}"
26
+ except Exception as e:
27
+ return f"Error: {str(e)}"
28
 
29
  # 🔥 Available models (you can update this)
30
  models = [
 
36
 
37
  # UI
38
  with gr.Blocks() as app:
39
+ gr.Markdown(f"# 🚀 Your Ollama UI")
40
+ gr.Markdown(f"**Connected to:** `{OLLAMA_BASE_URL}`")
41
 
42
  model_dropdown = gr.Dropdown(models, value="mistral", label="Select Model")
43
  prompt_input = gr.Textbox(lines=5, label="Enter Prompt")
next.config.js CHANGED
@@ -1,6 +1,9 @@
1
  /** @type {import('next').NextConfig} */
2
  const nextConfig = {
3
  reactStrictMode: true,
 
 
 
4
  }
5
 
6
  module.exports = nextConfig
 
1
  /** @type {import('next').NextConfig} */
2
  const nextConfig = {
3
  reactStrictMode: true,
4
+ env: {
5
+ OLLAMA_BASE_URL: process.env.OLLAMA_BASE_URL || 'http://localhost:11434',
6
+ },
7
  }
8
 
9
  module.exports = nextConfig
pages/api/generate.ts CHANGED
@@ -1,4 +1,36 @@
1
  import type { NextApiRequest, NextApiResponse } from "next"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
  export default async function handler(
4
  req: NextApiRequest,
@@ -11,12 +43,22 @@ export default async function handler(
11
  const { model, prompt } = req.body
12
 
13
  try {
14
- const ollamaRes = await fetch("http://localhost:11434/api/generate", {
 
 
 
 
 
 
 
 
 
 
15
  method: "POST",
16
  headers: { "Content-Type": "application/json" },
17
  body: JSON.stringify({
18
  model,
19
- prompt,
20
  stream: false,
21
  }),
22
  })
@@ -24,6 +66,7 @@ export default async function handler(
24
  const data = await ollamaRes.json()
25
  res.status(200).json(data)
26
  } catch (err) {
 
27
  res.status(500).json({ error: "Failed to connect to Ollama" })
28
  }
29
  }
 
1
  import type { NextApiRequest, NextApiResponse } from "next"
2
+ import fs from "fs"
3
+ import path from "path"
4
+
5
+ const CHAT_HISTORY_FILE = path.join(process.cwd(), "chat-history.json")
6
+
7
+ interface ChatMessage {
8
+ role: "user" | "assistant" | "system"
9
+ content: string
10
+ }
11
+
12
+ // Get Ollama base URL from environment variable
13
+ const OLLAMA_BASE_URL = process.env.OLLAMA_BASE_URL || "http://localhost:11434"
14
+
15
+ // Read chat history from file
16
+ function readChatHistory(): ChatMessage[] {
17
+ try {
18
+ if (fs.existsSync(CHAT_HISTORY_FILE)) {
19
+ const data = fs.readFileSync(CHAT_HISTORY_FILE, "utf-8")
20
+ const history = JSON.parse(data)
21
+ // Convert stored messages to Ollama format (only user and assistant roles)
22
+ return history.messages
23
+ .filter((msg: any) => msg.role === "user" || msg.role === "assistant")
24
+ .map((msg: any) => ({
25
+ role: msg.role,
26
+ content: msg.content,
27
+ }))
28
+ }
29
+ } catch (error) {
30
+ console.error("Error reading chat history:", error)
31
+ }
32
+ return []
33
+ }
34
 
35
  export default async function handler(
36
  req: NextApiRequest,
 
43
  const { model, prompt } = req.body
44
 
45
  try {
46
+ // Get conversation history
47
+ const conversationHistory = readChatHistory()
48
+
49
+ // Add current user message to the conversation
50
+ const messages = [
51
+ ...conversationHistory,
52
+ { role: "user" as const, content: prompt },
53
+ ]
54
+
55
+ // Use chat endpoint instead of generate to maintain conversation context
56
+ const ollamaRes = await fetch(`${OLLAMA_BASE_URL}/api/chat`, {
57
  method: "POST",
58
  headers: { "Content-Type": "application/json" },
59
  body: JSON.stringify({
60
  model,
61
+ messages,
62
  stream: false,
63
  }),
64
  })
 
66
  const data = await ollamaRes.json()
67
  res.status(200).json(data)
68
  } catch (err) {
69
+ console.error("Ollama API error:", err)
70
  res.status(500).json({ error: "Failed to connect to Ollama" })
71
  }
72
  }
pages/api/models.ts CHANGED
@@ -1,6 +1,7 @@
1
  import type { NextApiRequest, NextApiResponse } from "next"
2
 
3
- const OLLAMA = "http://localhost:11434"
 
4
 
5
  export default async function handler(
6
  req: NextApiRequest,
@@ -9,7 +10,7 @@ export default async function handler(
9
  // GET → list all models
10
  if (req.method === "GET") {
11
  try {
12
- const r = await fetch(`${OLLAMA}/api/tags`)
13
  const data = await r.json()
14
  res.status(200).json(data)
15
  } catch {
@@ -22,7 +23,7 @@ export default async function handler(
22
  if (req.method === "DELETE") {
23
  const { name } = req.body
24
  try {
25
- const r = await fetch(`${OLLAMA}/api/delete`, {
26
  method: "DELETE",
27
  headers: { "Content-Type": "application/json" },
28
  body: JSON.stringify({ name }),
 
1
  import type { NextApiRequest, NextApiResponse } from "next"
2
 
3
+ // Get Ollama base URL from environment variable
4
+ const OLLAMA_BASE_URL = process.env.OLLAMA_BASE_URL || "http://localhost:11434"
5
 
6
  export default async function handler(
7
  req: NextApiRequest,
 
10
  // GET → list all models
11
  if (req.method === "GET") {
12
  try {
13
+ const r = await fetch(`${OLLAMA_BASE_URL}/api/tags`)
14
  const data = await r.json()
15
  res.status(200).json(data)
16
  } catch {
 
23
  if (req.method === "DELETE") {
24
  const { name } = req.body
25
  try {
26
+ const r = await fetch(`${OLLAMA_BASE_URL}/api/delete`, {
27
  method: "DELETE",
28
  headers: { "Content-Type": "application/json" },
29
  body: JSON.stringify({ name }),
pages/api/pull.ts CHANGED
@@ -1,5 +1,8 @@
1
  import type { NextApiRequest, NextApiResponse } from "next"
2
 
 
 
 
3
  export default async function handler(
4
  req: NextApiRequest,
5
  res: NextApiResponse
@@ -15,7 +18,7 @@ export default async function handler(
15
  }
16
 
17
  try {
18
- const r = await fetch("http://localhost:11434/api/pull", {
19
  method: "POST",
20
  headers: { "Content-Type": "application/json" },
21
  body: JSON.stringify({ name, stream: false }),
 
1
  import type { NextApiRequest, NextApiResponse } from "next"
2
 
3
+ // Get Ollama base URL from environment variable
4
+ const OLLAMA_BASE_URL = process.env.OLLAMA_BASE_URL || "http://localhost:11434"
5
+
6
  export default async function handler(
7
  req: NextApiRequest,
8
  res: NextApiResponse
 
18
  }
19
 
20
  try {
21
+ const r = await fetch(`${OLLAMA_BASE_URL}/api/pull`, {
22
  method: "POST",
23
  headers: { "Content-Type": "application/json" },
24
  body: JSON.stringify({ name, stream: false }),
pages/index.tsx CHANGED
@@ -178,7 +178,7 @@ export default function Home() {
178
  const assistantMessage: ChatMessage = {
179
  id: `assistant-${Date.now()}`,
180
  role: "assistant",
181
- content: data.response || data.error || "No response",
182
  timestamp: Date.now(),
183
  model,
184
  }
 
178
  const assistantMessage: ChatMessage = {
179
  id: `assistant-${Date.now()}`,
180
  role: "assistant",
181
+ content: data.message?.content || data.response || data.error || "No response",
182
  timestamp: Date.now(),
183
  model,
184
  }