<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[davidlee2026]]></title><description><![CDATA[Practical, auditable workflows for turning authorized review text into evidence-backed product insights. Built by the developer of the Apparel Review Issue & Tr]]></description><link>https://davidlee2026.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Tue, 03 Nov 2026 03:37:56 GMT</lastBuildDate><atom:link href="https://davidlee2026.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How to keep review-analysis counts auditable with evidence quotes]]></title><description><![CDATA[Build an auditable review-analysis workflow with exact source quotes, a negation test, and spreadsheet-safe evidence.]]></description><link>https://davidlee2026.hashnode.dev/how-to-keep-review-analysis-counts-auditable-with-evidence-quotes</link><guid isPermaLink="true">https://davidlee2026.hashnode.dev/how-to-keep-review-analysis-counts-auditable-with-evidence-quotes</guid><category><![CDATA[data analysis]]></category><category><![CDATA[Python]]></category><category><![CDATA[ecommerce]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[david lee]]></dc:creator><pubDate>Sat, 31 Oct 2026 01:23:23 GMT</pubDate><content:encoded><![CDATA[<p>Most review-analysis demos end with a chart. The harder question starts one minute later:</p>
<blockquote>
<p>Why did this complaint count go up?</p>
</blockquote>
<p>If the result cannot point back to the source review, a product or support team has to search the raw text again. This tutorial uses a deliberately small synthetic apparel example to show a more auditable output contract: every aggregate keeps review IDs and exact evidence quotes.</p>
<h2>Fastest key-free check</h2>
<p>If you already have two authorized English reviews, open the <a href="https://apify.com/davidlee2026/my-actor/input-schema">public Apify Actor input form</a>, keep <code>mode</code> set to <code>rules</code>, and paste this input:</p>
<pre><code class="language-json">{
  "mode": "rules",
  "reviews": [
    {"id": "check-1", "product": "Demo shirt", "text": "Too small across the shoulders."},
    {"id": "check-2", "product": "Demo shirt", "text": "Not too small. Fits perfectly."}
  ]
}
</code></pre>
<p>This key-free check should preserve the first sentence as evidence and avoid counting the negated second sentence as a sizing complaint. Download the dataset, complete <code>OUTPUT</code> JSON, or <code>REPORT.csv</code> from the run results. Rules mode is only a narrow diagnostic, not full semantic analysis. A successfully completed report still costs <code>$0.03</code>; no TokenHub key or model fee is needed for this rules check. Apify currently labels the launch button <code>Try for free</code>; that label opens the console and is not a price promise. Review the <a href="https://apify.com/davidlee2026/my-actor/pricing">current Store pricing</a> before running.</p>
<h2>1. Start with a narrow input contract</h2>
<p>Use supplied, authorized review text rather than mixing collection and analysis into one opaque step. A minimal input can look like this:</p>
<pre><code class="language-json">{
  "mode": "rules",
  "reviews": [
    {
      "id": "demo-1",
      "product": "Demo shirt",
      "text": "Too small across the shoulders.",
      "rating": 2
    },
    {
      "id": "demo-2",
      "product": "Demo shirt",
      "text": "Not too small. Fits perfectly.",
      "rating": 5
    }
  ]
}
</code></pre>
<p>Both reviews are synthetic. The second one is important because a keyword-only counter may classify <code>small</code> as a complaint even though the sentence negates it.</p>
<h2>2. Make the aggregate traceable</h2>
<p>For this input, the expected small-sizing aggregate is one mention across two reviews, or a share of <code>0.5</code>. The output should retain the evidence that produced the count:</p>
<pre><code class="language-json">{
  "product": "Demo shirt",
  "topic": "size_small",
  "mentions": 1,
  "shareOfReviews": 0.5,
  "trend": "insufficient_data",
  "evidence": [
    {
      "reviewId": "demo-1",
      "quote": "Too small across the shoulders.",
      "rating": 2
    }
  ]
}
</code></pre>
<p>This structure lets a reviewer inspect the claim without trusting the aggregate blindly. It also makes false positives easier to debug: if <code>demo-2</code> appears in the evidence array, the negation rule or semantic classifier needs attention.</p>
<h2>What a buyer actually gets</h2>
<p>The useful output is not six counters. It is a short decision-support trail: the main recurring problems, the exact customer quotes behind them, and clearly labeled questions for a human to verify next. For example, a shoulder-fit complaint can prompt a size-chart measurement check; a seam failure can prompt a retained-sample wash test. Those are investigation hypotheses, not proven causes or promised improvements.</p>
<h2>3. Separate evidence from confidence</h2>
<p>An exact quote proves that the report copied text from a specific review. It does <strong>not</strong> prove that the topic classification is correct. That distinction should remain visible in both the schema and the documentation.</p>
<p>A practical report can keep these fields separate:</p>
<ul>
<li><code>topic</code>: the assigned issue category</li>
<li><code>mentions</code>: the number of unique reviews assigned to it</li>
<li><code>shareOfReviews</code>: mentions divided by the product's reviewed-item count</li>
<li><code>evidence</code>: source review IDs and quotes</li>
<li><code>trend</code>: a cautious comparison only when both time windows have enough dated reviews</li>
</ul>
<p>For tiny samples, <code>insufficient_data</code> is more honest than a dramatic trend label.</p>
<h2>4. Export defensively</h2>
<p>CSV exports are often opened in spreadsheet software. Prefix cells that begin with <code>=</code>, <code>+</code>, <code>-</code>, or <code>@</code> so untrusted review text is not interpreted as a formula. Also deduplicate review IDs and cap input size before analysis; otherwise one repeated review can inflate both counts and model cost.</p>
<h2>5. State the operating boundary</h2>
<p>The implementation I built accepts up to 100 unique reviews and 30,000 unique text characters. It does not scrape reviews or fetch arbitrary URLs. Its rules mode is a limited diagnostic, not a substitute for broad semantic understanding. Semantic mode requires the customer's Tencent TokenHub key, which is a real setup trade-off rather than something to hide.</p>
<p>The public Apify Actor is here: <a href="https://apify.com/davidlee2026/my-actor">https://apify.com/davidlee2026/my-actor</a></p>
<p>It charges <code>$0.03</code> per successfully completed report, including Apify platform costs. Rules mode does not need a model key, but the successful report is still charged. Semantic mode separately uses the customer's TokenHub account and may incur that provider's model fees.</p>
<p>Public availability and technical tests do not prove customer demand, classification accuracy, or profitability. The useful design lesson is narrower: <strong>keep every aggregate close enough to its source evidence that a human can challenge it.</strong></p>
<p>If you maintain review-analysis pipelines, I would be interested in the failure case you find hardest to audit: negation, mixed opinions in one sentence, product variants, or time-window comparisons?</p>
]]></content:encoded></item></channel></rss>