# AI Product Intelligence Engine (`tomko5peter/ai-product-intelligence-engine`) Actor

- **URL**: https://apify.com/tomko5peter/ai-product-intelligence-engine.md
- **Developed by:** [Peter Tomko](https://apify.com/tomko5peter) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 1,000 deterministic check units

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## CatalogSentry — Product Feed Semantic Validator

### What does CatalogSentry do?

CatalogSentry scans a product feed (CSV, JSON, or Google Merchant XML) and finds the
issues that field-format validators miss: a title that says "256GB" while the description
says "128GB," two SKUs with the same GTIN, a product missing its brand, or two "variants"
in the same item group that are actually identical. Every finding is evidence-backed — it
names the exact SKU, quotes the conflicting values, and recommends a fix — never a vague
"this looks off" opinion. Run it on Apify with a feed URL or a small inline product list.

### Why use CatalogSentry?

Inconsistent catalogs cost merchants marketplace suspensions, confused customers, and lost
conversions. Traditional feed validators check that a field exists and is the right type —
they don't check that two fields *agree* with each other. CatalogSentry adds that layer:
deterministic, explainable checks on top of your existing feed, runnable on a schedule via
Apify so drift gets caught before it reaches the storefront.

### How to use CatalogSentry

1. Point `feedUrl` at your product feed, upload a file directly via `feedFile`, or pass a small
   `products` array inline for testing. If your file's own column headers don't match our field
   names, set `columnMapping` too — no need to reformat the file first.
2. Pick which `checks` to run (default: the 8 deterministic checks; 7 more are opt-in).
3. Run the Actor. Findings land in the default dataset; a summary lands in the key-value store.
4. Review findings, fix the source data, re-run to confirm.

### Input

| Field | Description |
|---|---|
| `feedUrl` | URL of the feed to download. |
| `feedFile` | Upload a feed file directly instead of a URL — resolves to a URL the same way `feedUrl` does. |
| `columnMapping` | Map your own column names to our schema when they don't already match, e.g. `{"Product Name": "title"}`. Optional — most standard headers are already auto-detected. |
| `feedFormat` | `csv` | `json` | `google_merchant_xml`. |
| `products` | Inline product records instead of `feedUrl` — handy for MCP tool calls. |
| `checks` | Which checks to run: `missing_attributes`, `title_description_contradiction`, `duplicate_detection`, `variant_consistency`, `image_technical_qa`, `gtin_checksum_validator`, `thin_content_description`, `price_outlier_detector` (all 8 on by default), plus 7 opt-in checks: `semantic_cannibalization` (deterministic, O(n²), with an optional AI-assisted embedding pass when configured), `semantic_duplicate_detection` / `image_description_alignment` / `seo_keyword_gap` / `visual_brand_consistency` / `category_voice_consistency` / `translation_consistency` (AI-assisted — no setup needed, just enable them). |
| `requiredAttributes` | Attribute keys required on every product (for `missing_attributes`). |
| `targetLanguages` | Required for `translation_consistency` — ISO codes to translate into and check for number drift, e.g. `["cs", "pl", "sk", "de"]`. |
| `categoryVoiceBriefs` | Required for `category_voice_consistency` — maps category names to a tone/positioning brief. A category with no brief is skipped, no cost. |
| `searchQueries` | Real search queries from your site, e.g. `[{"query": "red running shoes"}]`, for catalog-gap analysis. Persisted across runs — a gap is flagged only after showing up repeatedly. |
| `minDescriptionWords` | Word-count floor for `thin_content_description` (default 10). |
| `minCategorySize` / `priceOutlierZThreshold` | Tuning for `price_outlier_detector` (defaults: 5 products, z-score 3.5). |
| `maxProducts` | Safety limit on feed size per run (default 5000). |
| `maxVisionProducts` | Separate, smaller safety limit for the opt-in vision checks (default 50) — each costs one real inference call per product. |
| `maxEstimatedCostUsd` | A hard ceiling on this run's projected billing, checked before any check runs. If exceeded, `semantic_cannibalization`'s input (the one check whose cost grows with the square of catalog size) is trimmed to fit — other checks aren't auto-trimmed by this, bound those with `maxVisionProducts` or by disabling them. 0 = unlimited. |
| `maxFindingsPerCheck` | Keeps only the highest-severity findings from each check, independently per check, up to this many — doesn't reduce cost, just keeps a noisy catalog's output focused. Nonzero values below 10 are raised to 10. 0 = unlimited. |
| `brandStyleBrief` | Describe your expected product image style (e.g. "white background, studio lighting"). Required for `visual_brand_consistency` — leave empty to skip it. |

See `.actor/input_schema.json` for the full schema, and `actor_input/demo--input.json` for a
worked example with a capacity contradiction, a duplicate GTIN, a missing brand, and an
indistinguishable variant pair.

### Output

Each dataset item is one finding:

```json
{
  "type": "title_description_contradiction",
  "severity": "high",
  "sku": "SGS24-256",
  "entity": "Samsung Galaxy S24 256GB",
  "evidence": "title mentions capacity [262144.0] MB; description mentions capacity [131072.0] MB.",
  "explanation": "Storage/memory capacity differs between fields describing the same product.",
  "recommendation": "Verify the authoritative capacity and correct the inconsistent field.",
  "confidence": "high"
}
```

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

### Data table

| Field | Format |
|---|---|
| `sku` | text |
| `type` | text |
| `severity` | text (`low` | `medium` | `high`) |
| `evidence` | text |
| `recommendation` | text |
| `confidence` | text (`low` | `medium` | `high`) |

### Pricing / Cost estimation

Most checks are deterministic — no inference calls — so cost is driven entirely by feed size
and compute time. Enabling the optional AI-assisted check (`semantic_duplicate_detection`)
costs slightly more per product; no setup or external account needed on your end.

### Tips

- Pass a small `products` array while developing a new check before pointing it at a full feed.
- Set `requiredAttributes` to match your taxonomy's mandatory fields.

### FAQ, disclaimers, and support

This is an early-stage tool, validated once end-to-end against a real 995-product public catalog
(not yet against a real customer's own feed). Eight checks are fully deterministic (no AI
inference call) and run by default. Seven more are opt-in: `semantic_cannibalization` is deterministic by default with an
optional AI-assisted embedding pass; `semantic_duplicate_detection`, `image_description_alignment`,
`seo_keyword_gap`, `visual_brand_consistency`, `category_voice_consistency`, and
`translation_consistency` use this Actor's own built-in AI-assisted detection — all off by
default, just enable them in `checks`, no configuration needed on your end. Open an issue in this
repo for bugs or feature requests.

# Actor input Schema

## `feedUrl` (type: `string`):

URL of the product feed to download (CSV, JSON array, or Google Merchant XML). Leave empty if using 'Upload a file' or 'Products' below instead.

## `feedFile` (type: `string`):

Upload a CSV/JSON/XML feed file directly instead of pointing at a URL. If your file's column headers don't match our field names, also set 'Column mapping' below. Leave empty if using 'Feed URL' or 'Products' instead.

## `columnMapping` (type: `object`):

Map your feed's own column/field names to our schema when they don't already match — e.g. {"Product Name": "title", "Item SKU": "sku"}. Valid target fields: sku, title, description, brand, category, price, currency, availability, group_id, gtin, image_url. An unrecognized target field is ignored, not an error.

## `feedFormat` (type: `string`):

Format of the feed at feedUrl. Ignored if 'Products' is used instead.

## `products` (type: `array`):

Inline product records instead of feedUrl — useful for MCP tool calls and testing. Each item: {sku, title, description, brand, category, price, currency, availability, group_id, image_url, attributes: {...}}.

## `checks` (type: `array`):

Which checks to run on your feed. Add or remove any combination.

## `requiredAttributes` (type: `array`):

Attribute keys that must be present and non-empty on every product for the 'missing_attributes' check.

## `targetLanguages` (type: `array`):

Required for the 'translation_consistency' check. ISO language codes to translate into and check for number drift, e.g. \["cs", "pl", "sk", "de"]. Empty = check skipped entirely.

## `categoryVoiceBriefs` (type: `object`):

Required for the 'category_voice_consistency' check. Map category names to a tone/positioning brief, e.g. {"Baby & Mom": "warm, reassuring, speaks to a caring parent"}. A category with no brief is skipped entirely.

## `searchQueries` (type: `array`):

Real search queries from your site, for catalog-gap analysis. Each item: {"query": "red running shoes"}. Persisted across runs — a gap is only flagged once it's shown up repeatedly, not from one run's snapshot.

## `minDescriptionWords` (type: `integer`):

Descriptions shorter than this are flagged by 'thin_content_description'. Default 10 — calibrated against real feed data, not a generic SEO-content figure.

## `minCategorySize` (type: `integer`):

'price_outlier_detector' only runs on categories with at least this many priced products — too few samples make a median/outlier calculation meaningless. Default 5.

## `priceOutlierZThreshold` (type: `number`):

Modified z-score threshold for 'price_outlier_detector' — lower is more sensitive (flags more), must be greater than 0 or every priced product gets flagged. Default 3.5 (a standard statistical convention).

## `maxProducts` (type: `integer`):

Safety limit on feed size per run. 0 = unlimited.

## `maxVisionProducts` (type: `integer`):

Separate, smaller safety limit for opt-in 'vision' checks (e.g. image_description_alignment, seo_keyword_gap, visual_brand_consistency) that cost one real inference call per product. Applies per check, independent of maxProducts above. 0 = unlimited.

## `brandStyleBrief` (type: `string`):

Describe your expected product image style (e.g. 'white background, studio lighting, centered product shot'). Required for the 'visual_brand_consistency' check — leave empty to skip it entirely.

## `maxEstimatedCostUsd` (type: `number`):

A hard ceiling on this run's projected billing, checked before any check runs. If the projected cost would exceed it, 'semantic_cannibalization' (the one check whose cost grows with the square of catalog size) has its input trimmed to fit the budget, and a warning is logged. Other checks are not auto-trimmed by this — bound their cost with maxVisionProducts, or by disabling them. 0 = unlimited.

## `maxFindingsPerCheck` (type: `integer`):

Keeps only the highest-severity (then highest-confidence) findings from each check, up to this many — applied separately to every check, so this never hides one check's findings behind another's (e.g. a pairwise check that fires often won't crowd out a check that fires rarely). This does not reduce cost — the check still does the same work — it just keeps the output focused on what matters most on a large or noisy catalog. A nonzero value below 10 is treated as 10. 0 = unlimited.

## Actor input object example

```json
{
  "feedFormat": "csv",
  "checks": [
    "missing_attributes",
    "title_description_contradiction",
    "duplicate_detection",
    "variant_consistency",
    "image_technical_qa",
    "gtin_checksum_validator",
    "thin_content_description",
    "price_outlier_detector"
  ],
  "requiredAttributes": [
    "brand",
    "category",
    "price"
  ],
  "minDescriptionWords": 10,
  "minCategorySize": 5,
  "priceOutlierZThreshold": 3.5,
  "maxProducts": 5000,
  "maxVisionProducts": 50,
  "maxEstimatedCostUsd": 0,
  "maxFindingsPerCheck": 0
}
```

# Actor output Schema

## `findings` (type: `string`):

No description

## `summary` (type: `string`):

No description

## `healthScore` (type: `string`):

No description

## `healthHistory` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("tomko5peter/ai-product-intelligence-engine").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("tomko5peter/ai-product-intelligence-engine").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call tomko5peter/ai-product-intelligence-engine --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,tomko5peter/ai-product-intelligence-engine"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/VIIUCR1iuJavAuGsB/builds/bdAlQH6n3UYbf71eT/openapi.json
