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:
@@ -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 });
|
||||
|
||||
Reference in New Issue
Block a user