fix: previous commit redeployed

This commit is contained in:
talatops 2026-04-03 12:54:30 +05:00
parent aa871ff942
commit 9f5cd954e0
2 changed files with 9 additions and 164 deletions

View File

@ -7,16 +7,6 @@ type HistoryMessage = {
content: string
}
/** Customer is asking whether the store carries / sells a product (not policy/shipping). */
function isAskingAboutProductAvailability(query: string) {
return /\b(do you have|have any|have you got|carry|carrying|sell|selling|in stock|out of stock|stock|available|got any|do you sell|do you carry|looking for|can i (get|buy)|can you get)\b/i.test(
query.trim()
)
}
const NO_EVIDENCE_PRODUCT_REPLY =
"I do not see that item in this store’s catalog or FAQs I have access to, so I can’t confirm we carry it. If you have another product name or category from this shop, I can check again."
export async function generateStorefrontReply(params: {
storeId: string
query: string
@ -27,34 +17,6 @@ export async function generateStorefrontReply(params: {
const { storeId, query, visitorId, history } = params
const retrieval = await getBlendedStorefrontContext({ storeId, query })
// Hard guard: do not invent inventory. If they ask “do you have X?” and we have no product row and no KB/FAQ hit, answer without the LLM.
if (
isAskingAboutProductAvailability(query) &&
retrieval.productCount === 0 &&
retrieval.kbCount === 0
) {
logger.info("[STOREFRONT_AI_REPLY]", {
storeId,
visitorId,
queryLength: query.length,
kbHits: retrieval.kbCount,
productHits: retrieval.productCount,
latencyMs: Date.now() - startedAt,
fallbackUsed: true,
groundedSkipLlm: true,
error: null,
})
return {
content: NO_EVIDENCE_PRODUCT_REPLY,
meta: {
kbHits: retrieval.kbCount,
productHits: retrieval.productCount,
fallbackUsed: true,
},
}
}
const contextLines = retrieval.items.map(
(item, idx) => `[${idx + 1}] (${item.source}) ${item.title}: ${item.content}`
)
@ -68,13 +30,12 @@ export async function generateStorefrontReply(params: {
})) as GroqChatMessage[]
const system = [
"You are the JUNO storefront assistant. You ONLY answer using the Context block below (products, FAQs, knowledge chunks).",
"If the Context does not clearly support an answer, say you cannot find it in the catalog or docs you have—do NOT guess.",
"Never claim a product exists, is in stock, or that the store carries a category unless a Context line explicitly supports it.",
"Never invent website layout: no tabs, menus, dropdowns, or navigation paths unless they appear verbatim in Context.",
"Never invent URLs or deep links unless they appear in Context.",
"Do not affirm availability with “yes” unless a PRODUCT line or FAQ/KB line in Context clearly covers what the customer asked.",
"Be concise and friendly. Plain text only.",
"You are JUNO storefront assistant for an ecommerce store.",
"Use the provided context first (products, FAQs, knowledge).",
"If context is insufficient, ask one concise clarifying question.",
"Do not invent exact prices, stock or policy details that are not present.",
"Keep responses concise, friendly, and sales-supportive.",
"Return plain text only.",
].join(" ")
const user = [
@ -92,13 +53,13 @@ export async function generateStorefrontReply(params: {
]
const out = await groqChatCompletion(messages, {
temperature: 0.1,
temperature: 0.2,
maxTokens: 420,
timeoutMs: 28_000,
})
const fallback =
"I don’t have enough in the store’s catalog or FAQ context to answer that accurately. What product name or topic from this shop should I look for?"
"Thanks for your message. I do not have enough details right now. Could you share the product name or what exactly you want to know?"
const content = (out.content || "").trim() || fallback

View File

@ -7,128 +7,12 @@ type RetrievedContextItem = {
score: number
}
/** Strip generic words so "do you have socks?" does not match random KB via "you"/"do". */
const STOPWORDS = new Set([
"the",
"a",
"an",
"and",
"or",
"but",
"in",
"on",
"at",
"to",
"for",
"of",
"as",
"by",
"with",
"from",
"is",
"are",
"was",
"were",
"be",
"been",
"being",
"have",
"has",
"had",
"do",
"does",
"did",
"will",
"would",
"could",
"should",
"may",
"might",
"must",
"can",
"this",
"that",
"these",
"those",
"i",
"me",
"my",
"you",
"your",
"it",
"its",
"we",
"our",
"they",
"them",
"their",
"what",
"which",
"who",
"whom",
"whose",
"where",
"when",
"why",
"how",
"all",
"each",
"every",
"both",
"few",
"more",
"most",
"other",
"some",
"such",
"no",
"nor",
"not",
"only",
"own",
"same",
"so",
"than",
"too",
"very",
"just",
"any",
"there",
"here",
"about",
"into",
"through",
"during",
"before",
"after",
"above",
"below",
"between",
"under",
"again",
"further",
"then",
"once",
"please",
"thanks",
"thank",
"hello",
"hi",
"hey",
"yes",
"no",
"tell",
"give",
"get",
"got",
])
function tokenize(text: string) {
return text
.toLowerCase()
.split(/[^a-z0-9]+/g)
.map((t) => t.trim())
.filter((t) => t.length >= 2 && !STOPWORDS.has(t))
.filter((t) => t.length >= 2)
}
function scoreByTerms(text: string, terms: string[]) {