🔥 0
0
Lesson 5 of 10 22 min +200 XP

Product Q&A Agent

"Is this laptop good for video editing?" "Will this couch fit through a 30-inch doorway?" "Does the battery really last 2 days?"

Customers have specific questions before buying. A Product Q&A Agent uses RAG to answer accurately from your product data - specs, descriptions, and real customer reviews.

Without RAG

"I don't have specific information about this product. Please check the product page."

With RAG

"Yes! The M2 MacBook Pro can handle 4K video editing smoothly. According to specs, it has 32GB RAM and reviews mention it exports a 10-min 4K video in 8 minutes."

Data Sources for Product Q&A

Product Specs

Dimensions, weight, materials, technical specifications

Descriptions

Features, benefits, use cases, compatibility

Customer Reviews

Real-world usage, pros/cons, durability over time

Q&A History

Previously answered questions from the product page

Embedding Product Data for Q&A

from openai import OpenAI
from pinecone import Pinecone
from typing import Dict, List
import json

client = OpenAI()
pc = Pinecone(api_key="your-api-key")
index = pc.Index("product-qa")

def embed_product_for_qa(product: Dict) -> List[Dict]:
    """Create multiple embeddings for different aspects of a product"""

    vectors = []
    product_id = product["id"]

    # 1. Embed product overview (name + description)
    overview_text = f"""
    Product: {product['name']}
    Brand: {product['brand']}
    Category: {product['category']}
    Description: {product['description']}
    """
    vectors.append(create_vector(
        id=f"{product_id}_overview",
        text=overview_text,
        metadata={"product_id": product_id, "type": "overview", "name": product['name']}
    ))

    # 2. Embed technical specifications
    if product.get('specifications'):
        specs_text = f"Product: {product['name']}\nSpecifications:\n"
        for key, value in product['specifications'].items():
            specs_text += f"- {key}: {value}\n"

        vectors.append(create_vector(
            id=f"{product_id}_specs",
            text=specs_text,
            metadata={"product_id": product_id, "type": "specifications", "name": product['name']}
        ))

    # 3. Embed each review separately
    for i, review in enumerate(product.get('reviews', [])[:20]):  # Top 20 reviews
        review_text = f"""
        Product: {product['name']}
        Review ({review['rating']}/5 stars):
        Title: {review.get('title', 'No title')}
        {review['text']}
        """
        vectors.append(create_vector(
            id=f"{product_id}_review_{i}",
            text=review_text,
            metadata={
                "product_id": product_id,
                "type": "review",
                "rating": review['rating'],
                "name": product['name']
            }
        ))

    # 4. Embed Q&A pairs
    for i, qa in enumerate(product.get('questions', [])):
        qa_text = f"""
        Product: {product['name']}
        Question: {qa['question']}
        Answer: {qa['answer']}
        """
        vectors.append(create_vector(
            id=f"{product_id}_qa_{i}",
            text=qa_text,
            metadata={"product_id": product_id, "type": "qa", "name": product['name']}
        ))

    return vectors


def create_vector(id: str, text: str, metadata: Dict) -> Dict:
    """Create embedding vector with metadata"""
    embedding = client.embeddings.create(
        model="text-embedding-3-small",
        input=text
    ).data[0].embedding

    return {
        "id": id,
        "values": embedding,
        "metadata": {**metadata, "text": text[:1000]}  # Store truncated text for context
    }

The Product Q&A Agent

from langchain.agents import AgentExecutor, create_openai_tools_agent
from langchain.tools import Tool
from langchain_openai import ChatOpenAI
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder

class ProductQAAgent:
    def __init__(self, vector_index, openai_client):
        self.index = vector_index
        self.client = openai_client
        self.llm = ChatOpenAI(model="gpt-4o", temperature=0)

        # Define tools
        self.tools = [
            Tool(
                name="search_product_info",
                func=self.search_product_info,
                description="Search for product information including specs, descriptions, and features. Use when you need factual product details."
            ),
            Tool(
                name="search_customer_reviews",
                func=self.search_reviews,
                description="Search customer reviews for real-world feedback about the product. Use for questions about quality, durability, real-world usage."
            ),
            Tool(
                name="search_product_qa",
                func=self.search_qa,
                description="Search previously answered questions about the product. Use to see if this question has been asked before."
            )
        ]

        # Create agent
        self.agent = self._create_agent()

    def _create_agent(self):
        prompt = ChatPromptTemplate.from_messages([
            ("system", """You are a helpful product Q&A assistant for an e-commerce store.

Your job is to answer customer questions about specific products accurately and helpfully.

Guidelines:
1. Use the available tools to find relevant information
2. Always cite your sources (e.g., "According to the specs..." or "Customers mention...")
3. If you can't find the answer, say so honestly and suggest contacting support
4. For subjective questions, summarize what multiple reviewers say
5. Be concise but complete

Product being discussed: {product_name}"""),
            ("human", "{question}"),
            MessagesPlaceholder(variable_name="agent_scratchpad")
        ])

        agent = create_openai_tools_agent(self.llm, self.tools, prompt)
        return AgentExecutor(agent=agent, tools=self.tools, verbose=True)

    def search_product_info(self, query: str) -> str:
        """Search product specs and descriptions"""
        return self._search(query, filter_type=["overview", "specifications"])

    def search_reviews(self, query: str) -> str:
        """Search customer reviews"""
        return self._search(query, filter_type=["review"])

    def search_qa(self, query: str) -> str:
        """Search existing Q&A"""
        return self._search(query, filter_type=["qa"])

    def _search(self, query: str, filter_type: List[str], top_k: int = 5) -> str:
        """Internal search function"""
        query_embedding = self.client.embeddings.create(
            model="text-embedding-3-small",
            input=query
        ).data[0].embedding

        results = self.index.query(
            vector=query_embedding,
            top_k=top_k,
            include_metadata=True,
            filter={
                "product_id": self.current_product_id,
                "type": {"$in": filter_type}
            }
        )

        if not results.matches:
            return "No relevant information found."

        return "\n\n---\n\n".join([
            f"Source: {m.metadata['type']}\n{m.metadata['text']}"
            for m in results.matches
        ])

    def answer(self, product_id: str, product_name: str, question: str) -> str:
        """Answer a question about a specific product"""
        self.current_product_id = product_id

        result = self.agent.invoke({
            "product_name": product_name,
            "question": question
        })

        return result["output"]


# Usage
agent = ProductQAAgent(index, client)

answer = agent.answer(
    product_id="SKU-MACBOOK-M2",
    product_name="MacBook Pro 14-inch M2 Pro",
    question="Is this good for video editing? I work with 4K footage."
)
print(answer)

Example Q&A Interactions

Customer:

"Is this laptop good for video editing? I work with 4K footage."

Agent:

Yes, the MacBook Pro 14-inch with M2 Pro is excellent for 4K video editing. Here's why:

From the specs:
- M2 Pro chip with 12-core CPU and 19-core GPU
- 32GB unified memory (configurable to 96GB)
- Hardware-accelerated ProRes encoding/decoding

What customers say:
- "Exports my 10-minute 4K videos in about 8 minutes" (5-star review)
- "Handles DaVinci Resolve and Final Cut Pro without any lag" (5-star review)
- "The only downside is it gets warm during long renders" (4-star review)

For 4K editing, this is one of the best laptops available. The M2 Pro's media engine makes a real difference for video work.

Customer:

"What's the actual battery life? I don't trust the advertised numbers."

Agent:

Smart question! Here's what I found:

Advertised: Up to 18 hours of video playback

Real-world from reviewers:
- "With regular coding and browsing, I get about 10-12 hours" (verified purchase)
- "Heavy video editing drains it in about 5-6 hours" (verified purchase)
- "Light use like documents and email, easily 14+ hours" (verified purchase)

Bottom line: Expect 10-12 hours for typical productivity work, less for intensive tasks like video editing. Still among the best in its class.

Handling Tricky Questions

def answer_with_uncertainty_handling(self, product_id: str, product_name: str, question: str) -> str:
    """Answer with graceful handling of uncertainty"""

    result = self.agent.invoke({
        "product_name": product_name,
        "question": question
    })

    answer = result["output"]

    # Check if the agent found useful information
    if "No relevant information found" in str(result.get("intermediate_steps", [])):
        # Generate a helpful "I don't know" response
        fallback = self.client.chat.completions.create(
            model="gpt-4o-mini",
            messages=[
                {
                    "role": "system",
                    "content": """The customer asked a question we don't have data for.
Generate a helpful response that:
1. Acknowledges the question
2. Explains we don't have that specific information
3. Suggests alternatives (check product page, contact support, manufacturer website)
4. Offers to help with other questions"""
                },
                {
                    "role": "user",
                    "content": f"Product: {product_name}\nQuestion: {question}"
                }
            ]
        )
        return fallback.choices[0].message.content

    return answer

Tracking Q&A Quality

def log_qa_interaction(
    product_id: str,
    question: str,
    answer: str,
    sources_used: List[str],
    confidence: float
):
    """Log Q&A for quality monitoring and improvement"""

    log_entry = {
        "timestamp": datetime.now().isoformat(),
        "product_id": product_id,
        "question": question,
        "answer": answer,
        "sources_used": sources_used,
        "confidence": confidence,
        "answer_length": len(answer),
        "has_citations": "according to" in answer.lower() or "customers mention" in answer.lower()
    }

    # Store in database for analysis
    db.qa_logs.insert_one(log_entry)

    # Flag low-confidence answers for review
    if confidence < 0.7:
        db.qa_review_queue.insert_one(log_entry)

Key Takeaways

  • Use multiple data sources - Specs for facts, reviews for real-world feedback
  • Always cite sources - "According to specs..." builds trust
  • Handle uncertainty gracefully - Don't make up answers, offer alternatives
  • Log and improve - Track Q&A quality and flag issues for review

Next up: Policy and FAQ Chatbot - Build an agent that handles returns, shipping, and common questions.

🧠 Quick Quiz

Test your understanding of this lesson.

1

What sources should a Product Q&A agent use to answer questions?

2

How should the agent handle questions it cannot answer from available data?

3

Why is it important to cite sources in product Q&A responses?