feat: add SuggestAspectsAsync to AiAssistantService
This commit is contained in:
@@ -284,6 +284,59 @@ public class AiAssistantService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<Dictionary<string, string>> SuggestAspectsAsync(
|
||||||
|
string title, string description, List<CategoryAspect> aspects)
|
||||||
|
{
|
||||||
|
if (aspects.Count == 0) return new();
|
||||||
|
|
||||||
|
var aspectLines = aspects.Select(a =>
|
||||||
|
{
|
||||||
|
var line = $"- {a.Name} (required: {a.IsRequired})";
|
||||||
|
if (!a.IsFreeText && a.AllowedValues.Count > 0)
|
||||||
|
line += $" — allowed values: {string.Join(", ", a.AllowedValues.Take(10))}";
|
||||||
|
return line;
|
||||||
|
});
|
||||||
|
|
||||||
|
var prompt =
|
||||||
|
"You are an eBay UK listing expert. Based on this listing, suggest values for the " +
|
||||||
|
"eBay item specifics (aspects) listed below.\n\n" +
|
||||||
|
$"Title: {title}\n" +
|
||||||
|
$"Description: {description}\n\n" +
|
||||||
|
"Aspects needed:\n" +
|
||||||
|
string.Join("\n", aspectLines) + "\n\n" +
|
||||||
|
"Rules:\n" +
|
||||||
|
"- For aspects with 'allowed values', you MUST use one of those exact values.\n" +
|
||||||
|
"- If unsure about an aspect, omit it from the response rather than guess.\n" +
|
||||||
|
"- Return ONLY valid JSON — no markdown, no explanation:\n" +
|
||||||
|
"{\n" +
|
||||||
|
" \"Brand\": \"Apple\",\n" +
|
||||||
|
" \"Model\": \"iPhone 14\"\n" +
|
||||||
|
"}\n" +
|
||||||
|
"Use the exact aspect name as the key.";
|
||||||
|
|
||||||
|
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.Properties()
|
||||||
|
.Where(p => !string.IsNullOrEmpty(p.Value?.ToString()))
|
||||||
|
.ToDictionary(p => p.Name, p => p.Value!.ToString());
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return new();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<string> CallWithVisionAsync(IEnumerable<string> imageDataUrls, string textPrompt)
|
private async Task<string> CallWithVisionAsync(IEnumerable<string> imageDataUrls, string textPrompt)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(_apiKey))
|
if (string.IsNullOrEmpty(_apiKey))
|
||||||
|
|||||||
Reference in New Issue
Block a user