Add AI corrections/refinement to Photo Analysis view

Adds a Corrections box and "Refine with AI" button below the
description. User types what the AI got wrong (e.g. "earrings are
white gold with diamonds, not silver and zirconium") and clicks
Refine — the AI rewrites the title, description and price while
keeping all other analysis fields intact.

AiAssistantService.RefineWithCorrectionsAsync() sends the current
listing text + corrections as a single text prompt and parses the
JSON response back into the title/description/price fields.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Peter Foster
2026-04-13 17:53:06 +01:00
parent 41b88bca45
commit c02c69aaa6
3 changed files with 146 additions and 0 deletions

View File

@@ -134,6 +134,54 @@ public class AiAssistantService
}
}
/// <summary>
/// Takes an existing AI-generated listing and rewrites title, description and price
/// to incorporate user corrections (e.g. "earrings are white gold, not silver").
/// Returns the updated fields; other PhotoAnalysisResult fields are unchanged.
/// </summary>
public async Task<(string Title, string Description, decimal Price, string PriceReasoning)>
RefineWithCorrectionsAsync(string title, string description, decimal price, string corrections)
{
var prompt =
"You are an expert eBay UK seller. I have a listing with incorrect details that need fixing.\n\n" +
$"Current title: {title}\n" +
$"Current description:\n{description}\n\n" +
$"Current price: £{price:F2}\n\n" +
$"CORRECTIONS FROM SELLER: {corrections}\n\n" +
"Rewrite the listing incorporating these corrections. " +
"Return ONLY valid JSON — no markdown, no explanation:\n" +
"{\n" +
" \"title\": \"corrected eBay UK title, max 80 chars, keyword-rich\",\n" +
" \"description\": \"corrected full plain-text eBay UK description\",\n" +
" \"price_suggested\": 0.00,\n" +
" \"price_reasoning\": \"one sentence why this price\"\n" +
"}";
var json = await CallAsync(prompt);
try
{
JObject obj;
try { obj = JObject.Parse(json.Trim()); }
catch (JsonReaderException)
{
var m = System.Text.RegularExpressions.Regex.Match(json, @"```(?:json)?\s*(\{[\s\S]*?\})\s*```");
obj = JObject.Parse(m.Success ? m.Groups[1].Value : json.Trim());
}
return (
obj["title"]?.ToString() ?? title,
obj["description"]?.ToString() ?? description,
obj["price_suggested"]?.Value<decimal>() ?? price,
obj["price_reasoning"]?.ToString() ?? ""
);
}
catch (Exception ex)
{
throw new InvalidOperationException($"Could not parse AI refinement response: {ex.Message}");
}
}
/// <summary>Convenience wrapper — analyses a single photo.</summary>
public Task<PhotoAnalysisResult> AnalyseItemFromPhotoAsync(string imagePath)
=> AnalyseItemFromPhotosAsync(new[] { imagePath });