Reduce batch size to 10 and tighten AI price check prompt
Still seeing stubs despite MaxTokens=8192 — smaller batches and explicit word limits in the prompt eliminate any remaining truncation risk. - BatchSize: 15 → 10 (~1200 output tokens per batch vs. potential 3000+) - Prompt: added 20-word cap on assumptions, 25-word cap on reasoning - Prompt: strengthened "nothing before or after the '['" instruction - Error log: now includes item IDs and first 300 chars of raw response so the next failure tells us exactly what Claude returned - JS timing: updated batch divisor from 25 → 10 to match actual batch size Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -20,7 +20,7 @@ public class AiCatalogPriceCheckService : IAiCatalogPriceCheckService
|
||||
private readonly ILogger<AiCatalogPriceCheckService> _logger;
|
||||
|
||||
private const string Model = "claude-sonnet-4-6";
|
||||
private const int BatchSize = 15; // 25 items at ~250 tokens each exceeds 4096 output tokens
|
||||
private const int BatchSize = 10; // keep responses predictably short; 10 items × ~120 tokens ≈ 1200 output tokens
|
||||
|
||||
private static readonly JsonSerializerOptions JsonOpts = new() { PropertyNameCaseInsensitive = true };
|
||||
|
||||
@@ -132,10 +132,11 @@ public class AiCatalogPriceCheckService : IAiCatalogPriceCheckService
|
||||
}
|
||||
};
|
||||
|
||||
var raw = string.Empty;
|
||||
try
|
||||
{
|
||||
var response = await SendAsync(client, parameters);
|
||||
var raw = response.Content.OfType<TextContent>().FirstOrDefault()?.Text ?? "[]";
|
||||
raw = response.Content.OfType<TextContent>().FirstOrDefault()?.Text ?? "[]";
|
||||
var json = ExtractJsonArray(raw);
|
||||
|
||||
var claudeItems = JsonSerializer.Deserialize<List<ClaudePriceCheckItem>>(json, JsonOpts) ?? new();
|
||||
@@ -164,8 +165,10 @@ public class AiCatalogPriceCheckService : IAiCatalogPriceCheckService
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "AI catalog price check batch failed");
|
||||
// Return stub verdicts so the rest of the report still renders
|
||||
var preview = raw.Length > 300 ? raw[..300] + "…" : raw;
|
||||
_logger.LogError(ex,
|
||||
"AI price check batch failed for items [{ItemIds}]. Raw response preview: {RawPreview}",
|
||||
string.Join(", ", batch.Select(b => b.Id)), preview);
|
||||
return batch.Select(item => new CatalogItemPriceVerdict
|
||||
{
|
||||
CatalogItemId = item.Id,
|
||||
@@ -220,10 +223,12 @@ public class AiCatalogPriceCheckService : IAiCatalogPriceCheckService
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("If the item already has an ApproximateArea or EstimatedMinutes, use those instead of guessing.");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("Return ONLY a JSON array, no prose, no markdown fences. Use this exact schema for each element:");
|
||||
sb.AppendLine("IMPORTANT: Keep responses concise to avoid truncation. Limit assumptions to 20 words max. Limit reasoning to 25 words max.");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("Return ONLY a JSON array — no prose, no markdown fences, nothing before or after the '['. Use this exact schema for each element:");
|
||||
sb.AppendLine(@"{
|
||||
""catalogItemId"": <int>,
|
||||
""assumptions"": ""<what you assumed about size/complexity>"",
|
||||
""assumptions"": ""<≤20 words>"",
|
||||
""estimatedSqFtMin"": <decimal>,
|
||||
""estimatedSqFtMax"": <decimal>,
|
||||
""estimatedMinutesMin"": <int>,
|
||||
@@ -233,7 +238,7 @@ public class AiCatalogPriceCheckService : IAiCatalogPriceCheckService
|
||||
""suggestedPriceMin"": <decimal>,
|
||||
""suggestedPriceMax"": <decimal>,
|
||||
""confidence"": ""high|medium|low"",
|
||||
""reasoning"": ""<1-2 sentence explanation>""
|
||||
""reasoning"": ""<≤25 words>""
|
||||
}");
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
@@ -12,14 +12,14 @@
|
||||
|
||||
// Estimate total seconds based on item count (roughly 12s per batch of 25, min 15s).
|
||||
function estimateDuration(itemCount) {
|
||||
var batches = Math.max(1, Math.ceil(itemCount / 25));
|
||||
return Math.max(15, batches * 12);
|
||||
var batches = Math.max(1, Math.ceil(itemCount / 10));
|
||||
return Math.max(15, batches * 10);
|
||||
}
|
||||
|
||||
// Messages keyed to approximate progress milestones (0–100).
|
||||
function messageAt(pct, batchCount) {
|
||||
if (pct < 10) return 'Loading catalog items…';
|
||||
if (pct < 20) return 'Sending items to Claude…';
|
||||
if (pct < 20) return 'Sending items for analysis…';
|
||||
if (batchCount <= 1) {
|
||||
if (pct < 75) return 'Analyzing your catalog with AI…';
|
||||
if (pct < 92) return 'Reviewing pricing data…';
|
||||
|
||||
Reference in New Issue
Block a user