Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
170 changes: 170 additions & 0 deletions installation_guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
# eSim AI Chatbot - Generalized Installation and Setup Guide

## 1. Overview

Before you begin, ensure you have:

- **OS:** Windows 10/11 with WSL2, macOS, or Ubuntu Linux
- **RAM:** Minimum 8 GB
- **Disk Space:** At least 15 GB free
- **Internet:** Required for initial downloads

---

## 2. Install Required Dependencies (OS-Specific)

### Linux (Ubuntu/Debian)

```bash
sudo apt update && sudo apt upgrade -y
sudo apt install -y python3 python3-venv python3-pip git curl \
portaudio19-dev python3-pyaudio \
libgl1 libglib2.0-0 \
libxcb-xinerama0 libxkbcommon-x11-0 libgl1-mesa-glx
```

### macOS

```bash
brew install python3 portaudio git
```

### Windows (WSL2)

Open **PowerShell as Administrator** and run:

```powershell
wsl --install
```

Then restart your system and follow the Linux steps above inside WSL.

---

## 3. Install Ollama

Download and install Ollama from:

https://ollama.com

Start Ollama:

```bash
ollama serve
```

---

## 4. Download AI Models

Run the following commands:

```bash
ollama pull qwen2.5-coder:3b
ollama pull qwen2.5-coder:1.5b
ollama pull nomic-embed-text
ollama pull minicpm-v
ollama pull tinyllama:1.1b
```

Verify installation:

```bash
ollama list
```

---

## 5. Clone the Repository

```bash
git clone https://github.com/username/Repository_name

cd Repository_name
```

---

## 6. Set Up Python Environment

### Linux/macOS

```bash
python3 -m venv venv

source venv/bin/activate
```

### Windows

```powershell
python -m venv venv

venv\Scripts\activate
```

---

## 7. Install Python Packages

```bash
pip install --upgrade pip

pip install -r requirements.txt
```

---

## 8. Run the Chatbot

```bash
PYTHONPATH=src python3 -m frontEnd.Application
```

---

## 9. Daily Usage

```bash
cd esim-chatbot-pr34

source venv/bin/activate

ollama serve &

PYTHONPATH=src python3 -m frontEnd.Application
```

---
## 10. Voice output

```bash
sudo apt install -y espeak
```

## 11. Troubleshooting

### GUI Won't Open

- Restart WSL
- Check display settings

### Missing Models

Run:

```bash
ollama pull <model-name>
```

### Microphone Issues

```bash
pip install pyaudio
```

### Qt Plugin Errors

- Verify Qt libraries are properly installed

---
1 change: 0 additions & 1 deletion src/chatbot/image_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
except Exception as e:
HAS_PADDLE = False
print(f"[INIT] PaddleOCR init failed: {e}")
print("[INIT] Vision analysis unavailable. Text and netlist analysis still work.")


def encode_image(image_path: str) -> str:
Expand Down
126 changes: 38 additions & 88 deletions src/chatbot/ollama_runner.py
Original file line number Diff line number Diff line change
@@ -1,90 +1,40 @@
import os
import ollama
import json
import time
import json,time

# ==================== CLIENT ====================
# Model configuration
VISION_MODELS = {"primary": "minicpm-v:latest"}
TEXT_MODELS = {"default": "qwen2.5:3b"}
EMBED_MODEL = "nomic-embed-text"

ollama_client = ollama.Client(
host="http://localhost:11434",
timeout=300.0,
timeout=300.0,
)

# ==================== SETTINGS ====================

_SETTINGS_DIR = os.path.join(
os.path.expanduser("~"), ".local", "share", "esim-copilot"
)
_SETTINGS_PATH = os.path.join(_SETTINGS_DIR, "settings.json")

_DEFAULT_TEXT_MODEL = "qwen2.5:3b"
_DEFAULT_VISION_MODEL = "minicpm-v:latest"
EMBED_MODEL = "nomic-embed-text"


def load_model_settings() -> dict:
"""Load persisted model preferences from disk."""
try:
with open(_SETTINGS_PATH, "r", encoding="utf-8") as f:
return json.load(f)
except Exception:
return {}


def save_model_settings(text_model: str, vision_model: str) -> None:
"""Persist model preferences to disk."""
os.makedirs(_SETTINGS_DIR, exist_ok=True)
try:
with open(_SETTINGS_PATH, "w", encoding="utf-8") as f:
json.dump({"text_model": text_model, "vision_model": vision_model}, f, indent=2)
except Exception as e:
print(f"[SETTINGS] Failed to save: {e}")


def list_available_models() -> list:
"""Query Ollama for installed models. Returns list of model name strings."""
try:
resp = ollama_client.list()
names = [m["name"] for m in resp.get("models", [])]
return names if names else [_DEFAULT_TEXT_MODEL, _DEFAULT_VISION_MODEL]
except Exception:
return [_DEFAULT_TEXT_MODEL, _DEFAULT_VISION_MODEL, EMBED_MODEL]


# Load settings and initialise model dicts
_settings = load_model_settings()

VISION_MODELS = {"primary": _settings.get("vision_model", _DEFAULT_VISION_MODEL)}
TEXT_MODELS = {"default": _settings.get("text_model", _DEFAULT_TEXT_MODEL)}


def reload_model_settings() -> None:
"""Re-read settings from disk and update running dicts (called after save)."""
s = load_model_settings()
VISION_MODELS["primary"] = s.get("vision_model", _DEFAULT_VISION_MODEL)
TEXT_MODELS["default"] = s.get("text_model", _DEFAULT_TEXT_MODEL)


# ==================== VISION ====================

def run_ollama_vision(prompt: str, image_input) -> str:
"""Call vision model with Chain-of-Thought for better accuracy."""
def run_ollama_vision(prompt: str, image_input: str | bytes) -> str:
"""Call minicpm-v:latest with Chain-of-Thought for better accuracy."""
model = VISION_MODELS["primary"]

try:
import base64

image_b64 = ""


if isinstance(image_input, bytes):
image_b64 = base64.b64encode(image_input).decode("utf-8")
elif isinstance(image_input, str) and os.path.isfile(image_input):

elif os.path.isfile(image_input):
with open(image_input, "rb") as f:
image_b64 = base64.b64encode(f.read()).decode("utf-8")

elif isinstance(image_input, str) and len(image_input) > 100:
image_b64 = image_input
image_b64 = image_input
else:
raise ValueError("Invalid image input format")
raise ValueError("Invalid image input format")

# === CHAIN OF THOUGHT ===
system_prompt = (
"You are an expert Electronics Engineer using eSim.\n"
"Analyze the schematic image carefully.\n\n"
Expand Down Expand Up @@ -115,7 +65,7 @@ def run_ollama_vision(prompt: str, image_input) -> str:
{
"role": "user",
"content": prompt,
"images": [image_b64],
"images": [image_b64], # <--- MUST BE LIST OF BASE64 STRINGS
},
],
options={
Expand All @@ -126,17 +76,18 @@ def run_ollama_vision(prompt: str, image_input) -> str:
)

content = resp["message"]["content"]


# === PARSE JSON FROM MIXED OUTPUT ===
import re
json_match = re.search(r'```json\s*(\{.*?\})\s*```', content, re.DOTALL)
if json_match:
return json_match.group(1)

start = content.find('{')
end = content.rfind('}') + 1
if start != -1 and end != -1:
return content[start:end]

return "{}"

except Exception as e:
Expand All @@ -145,45 +96,44 @@ def run_ollama_vision(prompt: str, image_input) -> str:
"vision_summary": f"Vision failed: {str(e)[:50]}",
"component_counts": {},
"circuit_analysis": {"circuit_type": "Error", "design_errors": [], "design_warnings": []},
"components": [],
"values": {},
"components": [], "values": {}
})


# ==================== TEXT ====================

def run_ollama(prompt: str, mode: str = "default") -> str:
"""Run text model with focused parameters."""
"""
OPTIMIZED: Run text model with focused parameters.
"""
model = TEXT_MODELS.get(mode, TEXT_MODELS["default"])

try:
resp = ollama_client.chat(
model=model,
messages=[
{
"role": "system",
"content": "You are an eSim and electronics expert. Be concise, accurate, and practical.",
"content": "You are an eSim and electronics expert. Be concise, accurate, and practical."
},
{"role": "user", "content": prompt},
],
options={
"temperature": 0.05,
"num_ctx": 2048,
"num_predict": 400,
"temperature": 0.05,
"num_ctx": 2048,
"num_predict": 400,
"top_p": 0.9,
"repeat_penalty": 1.1,
"repeat_penalty": 1.1,
},
)

return resp["message"]["content"].strip()

except Exception as e:
return f"[Error] {str(e)}"


# ==================== EMBEDDINGS ====================

def get_embedding(text: str):
"""Get text embeddings for RAG."""
"""
OPTIMIZED: Get text embeddings for RAG.
"""
try:
r = ollama_client.embeddings(model=EMBED_MODEL, prompt=text)
return r["embedding"]
Expand Down
Loading