Skip to content

Allow this site to count your visits with Yandex Metrica? Metrica will store cookies in your browser to do this. How the site uses cookies

VC
Case 3 of 25 · Retail · AI sales assistant

A store's own AI sales assistant beat a paid chat widget 34 : 12 in a blind test

A US outdoor-gear brand used a paid chat widget on its online stores. The widget was billed per store and often replied to a question with a question. The brand's Russian site had one more strict rule: customer data must stay in Russia. I built the brand its own chat assistant. It answers only from the brand's catalogue and documents; this technique is called retrieval-augmented generation (RAG). It runs on Russian language models. In a blind test against the paid widget it won 34 questions to 12.

Industry
Retail, outdoor gear
Technology
Python · FastAPI · RAG · YandexGPT
Timeline
4 weeks to launch, then ongoing support
Outcome
Won a blind test 34 : 12
01 · Problem

Every new store raised the bill, and the bot kept answering questions with questions

The brand runs two Shopify stores and a separate Russian site. The two stores used a paid chat widget billed per store, so the cost grew with every new store.

The team's main complaint was quality. When a customer asked whether a product suited a particular job, the widget often replied with a clarifying question. When it did answer, it pointed to whatever was in its own product feed and ignored the job the customer had described.

The Russian site had one more strict rule: customer data must not leave Russia. That ruled out foreign model providers for customer conversations, even "temporarily, just for the pilot". This rule alone narrowed the choice of ready-made chat widgets a great deal.

So the brief was an assistant that answers from the real catalogue and the real shipping and warranty terms, keeps customer data in Russia, and does at least as well as the paid widget, with numbers to prove it.

02 · Solution

Its own knowledge base, gateway and server

I built it as a separate project with four parts: a base of product facts, search over that base, a gateway that streams the answer, and a chat window that embeds on any site. Every answer is built from facts you can point to. Quality is checked by a test against a set of known correct answers.

01
Facts

562 facts: catalogue, FAQ, shipping and warranty, plus wording taken from real sales conversations

02
Search

Embeddings over the fact base pick out the facts that matter for each question

03
Gateway

FastAPI with a streamed answer (SSE), one interface for three language models, token refresh, retries and spending limits

04
Answer

The text streams first, then a separate message brings product cards with photos

05
After the answer

Conversations and contact requests go to log files, and a copy of every exchange goes to a person on Telegram

The facts come from the catalogue and from real conversations

The base holds 562 facts: product specs, FAQ, shipping and warranty terms. The most useful source was 335 real conversations between the sales team and customers, 131 of them about stock. From them I took the answers and also the way people actually ask about size, weight, winter use and delivery times. A bot trained on marketing copy doesn't recognise questions put that way.

One gateway for three language models

The gateway sits on top of the search and streams the answer (SSE), so the customer reads it as it's written. Behind one interface sit three providers. YandexGPT answers customers on the live site. GigaChat and DeepSeek are there for comparison tests and cheap experiments. Switching models doesn't touch the chat window. The routine but essential parts all live in the gateway:

  • access-token refresh and retries that respect Retry-After
  • one request at a time per session, so a single user can't start five answers at once
  • a spending cut-off, so abuse can't run up the model bill
  • phone numbers and emails are masked before logging, so they don't reach the conversation files
  • protection from bots with Cloudflare Turnstile
  • voice input: a customer can simply say the question

Product cards arrive right after the answer

The text goes out first, so the customer can start reading at once. Right after it, the gateway sends a separate message with cards for the products mentioned: photo, name and link. The advice stays easy to read, and the customer can go straight from the chat to the cart. Once the conversation gets specific, the chat also saves the customer's contact and passes it to a person.

Product cards got their photos back

For a while the cards under the bot's answers showed a placeholder letter where the product photo belonged. There were two causes at once. The daily catalogue update overwrote the file with records that had no image field, and the fixed list of image links had gone out of date after the site's links changed. Now the update takes the image straight from the store's API response, the first photo in the gallery, and checks its host the same way it checks links. Each run logs a "with photo: N of M" count, and a test on the index keeps the fix in place.

The request reaches sales with the whole conversation

A manager calls the customer back using the contact request, so the conversation behind it has to travel with the request. It used to live only in a log that was regularly overwritten. By the time a real request with a phone number came in, the conversation was already gone. Now the request carries the whole session. The two are joined by session ID, and the report labels the conversation with the name the customer gave. If the text had to be shortened, the report says so: "showing 2 of 5 turns, 3 more didn't fit".

Quality is checked by a test

The first quality check used a second model to grade the answers. I dropped it. It kept missing failures on exactly the category questions the sales team had complained about, and it passed any answer that sounded coherent. Now a fixed test does the job: for each question we know which facts must appear in the answer, and the check looks for them. On top of that there are 134 pytest tests, including grounding (every claim in an answer traces back to the fact base) and abuse protection.

The check for gaps in the knowledge base stopped marking correct answers as "evasive". The chat is not allowed to quote shipping costs or instalment rates; a manager calculates them. Such answers follow the store's own policy, yet the old rules would have sent them for repair. Now only "no data" and "not specified" count as a real gap, and "a manager will calculate it" is checked against the topic of the question. The "evasive" section is gone from the daily report; "weight not specified" still counts as a gap.

The tests needed work too. Seven of them failed with a type error, so they checked nothing. The test stand-in for the model still took two arguments after the working code had gained a third, for token-spend accounting. That left the captcha, the daily budget and replay protection untested. The same review found that one test run used up 810 of the 1,000 daily calls meant for site visitors. Local checks now have a separate counter.

Hard rules in code on top of the model

The three weeks after launch went into answer accuracy and data integrity. The store sent error reports as text and as voice notes; the voice notes are transcribed automatically and join the same queue. Two of the errors could have cost a customer money. Asked about an inflatable tent, the bot first suggested a weak 2 PSI pump that can't inflate it. It also said with confidence that a clear end wall comes in the box. It had confused the wall with the windows made of the same material, listed one line above in the specs.

Both are now fixed in code. The weak pump is filtered out of tent answers, and in the general list of pumps it comes with a note on what it's for. The end wall now has a lookup table for the three models with data on file. For every other model the bot gives one fixed answer: "no data on file, a manager will confirm".

The lesson for the next project: editing the knowledge base alone didn't help here. The model kept inferring "included" from the neighbouring spec line, as it had earlier with the stove safety rules. Where a wrong answer costs the customer money, the answer is fixed in code.

The index now contains every file it should

Six knowledge-base files were written specifically to answer the store's complaints: stock and dispatch, how to give advice, what's in the box, compatibility, use and care, delivery and payment. They were missing from the list of allowed sources, and the build skipped them without a warning. However many times the index was rebuilt, the bot knew nothing from those six files. They are now on the list.

One limitation remains: the index is stored outside the repository, and rebuilding it takes a person and a cloud key. Changes to the knowledge base reach the live chat only after that rebuild.

A step-by-step rollout on a live site

The site runs on a website builder, and every edit goes live at once. So I rolled the chat out in steps. First, a backup. The chat code was added to the end of the page's HEAD, and I checked that the existing markup stayed unchanged. Then one home page, a check on the live site, and only then the remaining pages, about sixty of them. The rollback takes three steps and is written down next to the instructions.

03 · Technology

Built to meet the data-residency rule

Python · FastAPI · uvicorn

The gateway that streams answers; runs as a systemd service on its own server

RAG: own fact base

562 facts plus embeddings; product cards have an index of their own

YandexGPT

Answers customers on the live site; the data stays in Russia

GigaChat · DeepSeek

Alternative models behind the same interface, for comparison tests and cheap experiments

Yandex SpeechKit

Voice input: a customer can simply say the question

Cloudflare Turnstile

Protection from abuse without making customers solve a captcha

JS widget

One snippet that embeds into a website-builder site without access to its source code

OpenTelemetry GenAI tracing

Each answer is traced from start to finish: search, model call, token spend

systemd

Services and timers on its own server, with an alert when one stops

pytest — 134 tests

Grounding, abuse protection and the fixed answer check that replaced the model grader

PythonFastAPISSERAGYandexGPTGigaChatDeepSeekSpeechKitTurnstileOpenTelemetrysystemdpytest
04 · Results

A blind test against the paid widget

Questions won
34 : 12

store's own assistant / paid widget, 3 ties

Answered with a question
43% 0

21 of 49 for the widget, none for the store's own assistant

Usefulness score
4.14 / 2.96

completeness: 3.98 and 2.90

Here is how the test was built. 49 questions were written from 174 real customer questions and spread over a grid of 7 customer types and 7 stages of buying, from "first time on the site" to "already decided, just checking the warranty". Every question went to both bots, the answers were shuffled, and the grading was blind: the grader never knew which bot gave which answer.

The biggest difference was whether the bot answered at all. On 21 of the 49 questions the paid widget replied with a question of its own, exactly what the sales team had complained about. The store's own assistant answered all 49 on the merits.

The chat is live on the site. One evening the business owner left a comment, and by morning two fixes were live: the bot stopped making up which products were popular and started going by actual sales. A fix that goes live the next day is a good sign that the system is easy to maintain.

The cost is also predictable: you pay for the tokens you use and for your own server. It doesn't grow with the number of stores, there are no licences, and the spending cut-off in the gateway keeps the bill under a set ceiling.

05 · Where it fits

Where the same approach works

The underlying task is common: give advice on a narrow subject, where every answer has to rest on facts. The same setup works wherever a company has its own body of knowledge and a wrong answer is expensive:

  • → Stores where choosing is hard: equipment, machinery, gear, anything a buyer needs explained
  • → B2B sites with long sales cycles: the chat sorts out the enquiry and hands it to sales with the conversation attached
  • → A helper for your support team: the same knowledge base suggests answers, so staff don't have to dig through policy documents
  • → Any field where data must stay in the country: healthcare, finance, the public sector. The setup is the same
  • → Replacing a subscription widget: when the fee grows with every location, store or brand, your own assistant can pay for itself
What I reuse on later projects
  • A streaming gateway with one interface for several model providers: switching models doesn't touch the chat window
  • The recipe for the knowledge base: catalogue, policies and real conversations
  • A fixed answer test against known correct facts. In this project a model grader missed exactly the failures it was meant to catch
  • A blind comparison test on questions built from real ones, spread over a grid of customer types and buying stages
  • A step-by-step rollout: backup, one page, a check on the live site, then the rest, with a three-step rollback
  • A copy of every conversation goes to a person on Telegram for the first few weeks, so someone sees what the bot says
Similar challenge?

If your chat widget answers questions with questions, it can be fixed

I start with the knowledge base and the way to check it: what the bot must know and how to prove that it knows it. In this project it took four weeks to go from a prototype to the live site. After that came ongoing work on reliability and accuracy.