Hi Codez,
Today I'm taking my first step toward building my own chatbot. Now, the obvious assumption is that you need a GPU like an NVIDIA CUDA-compatible card, plus a subscription to a high-level LLM like OpenAI's or Claude's models.
But here's the thing — as learners, we don't need any of that. You don't need a high-performance laptop with a beefy GPU, and you don't need to pay a monthly subscription in dollars just to experiment. Even with an old laptop — 16GB RAM (8GB works fine too) and no real GPU to speak of — you can still build something real, using open source tools.
Starting from nothing is actually the best way to learn exactly what you need. - My quote :)
The Goal
I wanted to build a working conversational chatbot — something with memory, a defined personality, and a real chat interface — but entirely offline. No API costs, no sending my conversations to a third-party server, and no dependency on an internet connection.
The Stack
- Miniconda — for setting up an isolated Python environment and managing libraries
- Ollama — to run a local LLM on your machine (no API keys, no cloud)
- LangChain — to handle prompts and conversation memory
- Streamlit — for a clean, simple chat interface in the browser
Step 1: Set Up Your Environment with Miniconda
If you don't already have Miniconda, download it from the official site and install it for your OS.
Step 2: Install and Run Ollama
Ollama is what makes this whole project possible without a GPU. It lets you download and run open source LLMs locally, with sensible defaults for CPU-only machines.
- Download Ollama from ollama.com and install it.
- Pull a lightweight model. For a machine with 8–16GB RAM, something like
llama3.2(3B) orphi3is a good starting point — small enough to run smoothly, capable enough to hold a real conversation:
ollama pull llama3.2
- Test that it works directly from the terminal:
ollama run llama3.2
If you get a response, your local LLM is live. No API key, no internet required after the download.
Step 3: Install the Python Dependencies
create a dedicated environment for this project, install the libraries we'll need:
I create yml file given below file named as environment.yml (save it in your project file path)
name: chatbot
channels:
- conda-forge
- defaults
dependencies:
- python=3.11
- pip
- pip:
- langchain
- langchain-ollama
- streamlit
-
langchain-ollamagives LangChain a direct connector to your local Ollama server -
streamlitwill handle the chat UI
In Terminal go to your project file path and run this command:
conda env create -f environment.yml
once its install all libraries and your activated conda environment.
conda activate chatbot
Step 4: Build the Chatbot Logic
Create a file called chatbot.py. This is where LangChain connects to your local model and keeps track of the conversation.
from langchain_ollama import ChatOllama
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.messages import HumanMessage , AIMessage
MODEL_NAME = 'llama3.2:3b'
ROLE = (
"Daisy — a young, intelligent AI companion with the calm confidence of a "
"world-class personal assistant. She's warm, quick-witted, emotionally aware, "
"and speaks like a smart Indian friend: natural, concise, and never robotic."
)
SYSTEM_PROMPT = f"""
You are Daisy.
## Personality
- Calm, confident, and highly capable.
- Friendly without being overly casual.
- Uses light, clever humour when it fits naturally.
- Loyal and genuinely looks out for the user's best interests.
- Takes initiative by suggesting better ideas, but never becomes pushy.
## Speaking style
- Use fluent, grammatically correct Indian English.
- Sound like a young professional (22–30), not formal or corporate.
- Keep conversations natural and conversational.
- Avoid American slang unless the user uses it first.
- Don't overuse emojis or exclamation marks.
## Behaviour
- Be proactive, practical, and honest.
- Explain complex topics simply.
- If the user is stressed, stay reassuring and solution-focused.
- Admit uncertainty instead of making things up.
Your name is Daisy.
"""
class DaisyChatbot:
def __init__(self, model_name = MODEL_NAME , role = ROLE, temperature=0.4 , max_tokens = 300):
self.model_name = model_name
self.role = role
self.history = []
self.llm = ChatOllama(
model = model_name,
temperature = temperature,
num_predict = max_tokens
)
self.prompt = ChatPromptTemplate.from_messages([
("system", SYSTEM_PROMPT),
MessagesPlaceholder(variable_name="history"),
("human", "{question}")
])
self.chain = self.prompt | self.llm
def ask(self, question: str) -> str:
"""Send a question to Daisy and get a reply, updating memory."""
response = self.chain.invoke({
"role": self.role,
"question": question,
"history": self.history
})
reply = response.content
self.history.append(HumanMessage(content=question))
self.history.append(AIMessage(content=reply))
return reply
def reset_memory(self):
"""Clear the conversation history."""
self.history = []
def run_cli(self):
"""Start an interactive terminal chat loop."""
print(f"Daisy is ready . Type 'quit' to exit.\n")
while True:
user_input = input("You: ")
if user_input.strip().lower() in ("quit", "exit", "bye"):
print("Daisy: Goodbye! Talk soon.")
break
reply = self.ask(user_input)
print(f"Daisy: {reply}\n")
In this code, I use the method format, including Prompt Template, to define how I want my chatbot to work. (If you need any specific requirements, just edit your prompt accordingly.)
Step 5: Build the Streamlit Interface
Create a second file, app.py, in the same folder:
import streamlit as st
from chatbot import DaisyChatbot
st.set_page_config(page_title="Daisy Chatbot", page_icon="🌼")
# ---- WhatsApp-style chat bubble CSS ----
st.markdown("""
<style>
.chat-row {
display: flex;
margin: 8px 0;
}
.chat-row.user {
justify-content: flex-end;
}
.chat-row.assistant {
justify-content: flex-start;
}
.bubble {
max-width: 70%;
padding: 10px 14px;
border-radius: 14px;
font-size: 15px;
line-height: 1.4;
word-wrap: break-word;
}
.bubble.user {
background-color: #DCF8C6;
color: #111;
border-bottom-right-radius: 4px;
}
.bubble.assistant {
background-color: #2A2F32;
color: #E9EDEF;
border-bottom-left-radius: 4px;
}
</style>
""", unsafe_allow_html=True)
st.markdown(
"""
<div style="text-align: center;">
<h1>🌼 Daisy Chatbot</h1>
<p style="color: gray; margin-top: -10px;">
Hi, my name is Daisy, and I'm here to help you with anything you need.
</p>
</div>
""",
unsafe_allow_html=True
)
# Initialize Daisy once per session, not on every rerun
if "daisy" not in st.session_state:
st.session_state.daisy = DaisyChatbot(model_name="llama3.2:3b")
# Track chat messages for display (separate from Daisy's internal memory)
if "messages" not in st.session_state:
st.session_state.messages = []
# Sidebar controls
with st.sidebar:
st.header("Settings")
if st.button("🔄 New Conversation"):
st.session_state.daisy.reset_memory()
st.session_state.messages = []
st.rerun()
def render_bubble(role: str, content: str):
st.markdown(
f'<div class="chat-row {role}"><div class="bubble {role}">{content}</div></div>',
unsafe_allow_html=True
)
# Display past messages
for msg in st.session_state.messages:
render_bubble(msg["role"], msg["content"])
# Chat input box
user_input = st.chat_input("Type your message to Daisy...")
if user_input:
# Show user message immediately
st.session_state.messages.append({"role": "user", "content": user_input})
render_bubble("user", user_input)
# Get Daisy's reply
with st.spinner("Daisy is thinking..."):
reply = st.session_state.daisy.ask(user_input)
render_bubble("assistant", reply)
st.session_state.messages.append({"role": "assistant", "content": reply})
Step 6: Run It
Make sure Ollama is running in the background (it usually starts automatically after install, or run ollama serve), then launch the app:
streamlit run app.py
Your browser will open a clean chat interface, and every response is generated locally on your own CPU — no cloud calls, no billing dashboard, no GPU required. (Shown in fig.1)
What You Actually Learned
This isn't just "installed some tools and it worked." Along the way you touched:
- How local LLM inference works without cloud APIs
- How LangChain structures conversation memory
- How to wire a model up to a real, usable frontend
That's the whole point of starting from nothing — every piece you added, you understand why it's there.
Where to Go From Here
- Swap
llama3.2for other Ollama models (mistral,phi3,gemma2) and compare responses - Add a system prompt to give your chatbot a personality
- Add
ConversationBufferMemoryfrom LangChain for more advanced memory handling - Try streaming responses token-by-token instead of waiting for the full reply
Next post, I'll share my next learning. Until then — happy building, my codez!

Top comments (0)