Class: Retailer::AnalysisPrompt

Inherits:
Object
  • Object
show all
Defined in:
app/services/retailer/analysis_prompt.rb

Overview

Builds the user message for a retailer-catalog AI analysis (the "Run
analysis" button on Crm::RetailersController#show). Follows the
DailyFocus::Prompt pattern: a compact deterministic data digest injected
up front plus instructions to dig deeper via the app_db tools for
anything the digest doesn't cover — never a blind "go look at the DB"
prompt. Everything the LLM is expected to cite (gap SKUs, AR figures)
is computed here from the database; the prompt forbids inventing SKUs
outright (a freeform "assortment gaps" ask produced hallucinated SKUs).

Constant Summary collapse

TOOL_SERVICES =

Tool services the analysis chat may use (execute_sql over the app DB).

%w[app_db].freeze
GAP_SAMPLE_SIZE =

How many gap SKUs the digest lists explicitly.

12

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(catalog, row) ⇒ AnalysisPrompt

Returns a new instance of AnalysisPrompt.

Parameters:

  • catalog (Catalog)
  • row (Hash, nil)

    the catalog's Retailer::DailyComplianceReport row



28
29
30
31
# File 'app/services/retailer/analysis_prompt.rb', line 28

def initialize(catalog, row)
  @catalog = catalog
  @row = row || {}
end

Class Method Details

.user_message(catalog:, row: nil) ⇒ String

Parameters:

  • catalog (Catalog)
  • row (Hash, nil) (defaults to: nil)

    the catalog's Retailer::DailyComplianceReport row

Returns:

  • (String)


24
# File 'app/services/retailer/analysis_prompt.rb', line 24

def self.user_message(catalog:, row: nil) = new(catalog, row).user_message

Instance Method Details

#user_messageString

Returns:

  • (String)


34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'app/services/retailer/analysis_prompt.rb', line 34

def user_message
  <<~PROMPT
    You are analyzing the health of our retailer channel "#{@catalog.name}" (catalog ##{@catalog.id}).
    Write a concise, operational analysis in Markdown.

    GROUND RULE — never invent SKUs, article numbers, or figures. Name only SKUs that appear verbatim
    in the snapshot below or in the results of your own execute_sql queries. If something cannot be
    verified in the database, say "not verified" instead of guessing. Every number you state must come
    from the snapshot or a query result.

    LINKS — when you reference a catalog item by SKU, link it to the catalog item search using this
    exact pattern: [SKU](/catalogs/#{@catalog.id}/catalog_items/search?q[sku_eq]=SKU). Never fabricate any
    other URLs.

    DATA SOURCES — only use tables/views that belong to THIS retailer ("#{@catalog.name}"). In
    particular, never query Amazon-specific tables or views (view_amazon_catalog_items, amazon_*
    tables, Amazon marketplace/ads data) for a non-Amazon catalog — an empty result there says
    nothing about this channel.

    ## Snapshot (fresh at generation time)

    #{digest}

    ## What to cover

    1. **Catalog health** — what shape is the assortment in? Call out anything deteriorating vs the snapshot's own context.
    2. **Sales health** — order volume and revenue trend. Use the app_db tools to pull the last ~6 months of sales_orders for this catalog (orders join customers on catalogs) if the snapshot isn't enough.
    3. **Accounts receivable & profitability** — review the AR snapshot below: unpaid/overdue exposure, days-to-pay trend, deductions or fees the channel subtracts, and overall profitability of the account. Use execute_sql on invoices/payments (invoices join parties on parties.catalog_id) for anything beyond the snapshot.
    4. **Actionable errors** — open listing issues and probe failures: what should a human do about each cluster, in priority order?
    5. **Pending onboarding** — items in pending_onboarding state: what are they, and is anything blocking them from going live?
    6. **Assortment gaps** — work ONLY from the verified gap list in the snapshot (items active in the parent catalog but missing here). Do NOT name any SKU outside that list or your own query results.
    7. **Advertising** — #{advertising_instruction}
    8. **Anything else** — anomalies in the data that don't fit the buckets above.

    End with a short **"Top 3 actions"** list, most impactful first.
  PROMPT
end