The Problem: Support That Doesn't Scale
An online clothing store in Barcelona was losing customers. Their support team couldn't handle the volume of inquiries — response times stretched to hours, and there was zero personalization. The challenge was clear: build an AI-powered chatbot that could recommend products, answer questions, and drive sales automatically. This became one of my most impactful projects.
Architecture Overview
The system has three main components: a Django REST API backend, OpenAI's GPT model for natural language understanding, and a PostgreSQL database for conversation history and product catalog.
chatbot/
+-- api/
| +-- views.py # Chat endpoint
| +-- serializers.py # Request/response validation
+-- ai/
| +-- engine.py # OpenAI integration
| +-- prompts.py # System prompts
| +-- context.py # Conversation history
+-- catalog/
| +-- models.py # Product, Category
| +-- search.py # Product search logic
+-- analytics/
+-- tracker.py # Conversation metrics
OpenAI Integration
The core of the chatbot is the OpenAI API integration:
import openai
from django.conf import settings
class ChatEngine:
def __init__(self):
self.client = openai.OpenAI(api_key=settings.OPENAI_API_KEY)
def get_response(self, user_message, conversation_history, products):
system_prompt = self.build_system_prompt(products)
messages = [{"role": "system", "content": system_prompt}]
messages.extend(conversation_history[-10:])
messages.append({"role": "user", "content": user_message})
response = self.client.chat.completions.create(
model="gpt-4o-mini",
messages=messages,
temperature=0.7,
max_tokens=500,
)
return response.choices[0].message.content
def build_system_prompt(self, products):
product_list = "\n".join(
f"- {p.name}: {p.description} (EUR {p.price})"
for p in products[:20]
)
return f"You are a helpful fashion advisor for our store.\n"
f"Available products:\n{product_list}\n\n"
f"Rules: Recommend specific products with prices. "
f"Be friendly and concise."
Conversation History Management
Maintaining context across messages is crucial. Each conversation gets a session with full history stored in PostgreSQL:
class Conversation(models.Model):
session_id = models.UUIDField(default=uuid.uuid4, unique=True)
customer_email = models.EmailField(blank=True)
created_at = models.DateTimeField(auto_now_add=True)
class Message(models.Model):
conversation = models.ForeignKey(Conversation, related_name='messages')
role = models.CharField(max_length=10) # user / assistant
content = models.TextField()
timestamp = models.DateTimeField(auto_now_add=True)
tokens_used = models.IntegerField(default=0)
Product Recommendation Logic
Beyond simple keyword matching, I implemented a two-stage recommendation approach. First, the system identifies intent (browsing, specific search, style advice). Then it queries the catalog with relevant filters:
def find_relevant_products(user_message, category=None):
keywords = extract_keywords(user_message)
queryset = Product.objects.filter(in_stock=True)
if category:
queryset = queryset.filter(category=category)
query = Q()
for keyword in keywords:
query |= Q(name__icontains=keyword)
query |= Q(description__icontains=keyword)
return queryset.filter(query)[:20]
The Django Chat Endpoint
class ChatView(APIView):
def post(self, request):
serializer = ChatSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
session_id = serializer.validated_data['session_id']
user_message = serializer.validated_data['message']
conversation, _ = Conversation.objects.get_or_create(
session_id=session_id
)
Message.objects.create(
conversation=conversation, role='user', content=user_message
)
history = [
{"role": m.role, "content": m.content}
for m in conversation.messages.order_by('timestamp')
]
products = find_relevant_products(user_message)
engine = ChatEngine()
response_text = engine.get_response(user_message, history, products)
Message.objects.create(
conversation=conversation, role='assistant', content=response_text
)
return Response({'response': response_text})
Prompt Engineering Tips
The system prompt is everything. Here's what I learned:
- Include product data directly in the prompt — the AI can't browse your catalog
- Set clear boundaries — tell the AI what it should and shouldn't discuss
- Use few-shot examples — include 2-3 example conversations in the system prompt
- Limit response length — customers prefer short, direct answers
- Handle "I don't know" gracefully — redirect to human support when needed
Results
After deployment, the chatbot handled 70% of customer inquiries automatically, and online conversion increased by 35%. Response time went from hours to seconds. The key was making the AI feel like a knowledgeable fashion advisor, not a generic bot.
Looking to build a similar AI integration? Check out my guide on integrating OpenAI into production Django apps, or explore my AI integration services.