Organize workspace: Frontend, Backend, and Tests in one repo
This commit is contained in:
55
.vscode-server/data/User/History/b03096/26Rk.cs
Normal file
55
.vscode-server/data/User/History/b03096/26Rk.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using Seasoned.Backend.DTOs;
|
||||
using Mscc.GenerativeAI;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System.IO;
|
||||
|
||||
namespace Seasoned.Backend.Services;
|
||||
|
||||
public class RecipeService : IRecipeService
|
||||
{
|
||||
private readonly string _apiKey;
|
||||
|
||||
public RecipeService(IConfiguration config)
|
||||
{
|
||||
_apiKey = config["GeminiApiKey"] ?? throw new ArgumentNullException("API Key missing");
|
||||
}
|
||||
|
||||
public async Task<RecipeResponseDto> ParseRecipeImageAsync(IFormFile image)
|
||||
{
|
||||
var googleAI = new GoogleAI(_apiKey);
|
||||
var model = googleAI.GenerativeModel("gemini-2.5-flash");
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
await image.CopyToAsync(ms);
|
||||
var base64Image = Convert.ToBase64String(ms.ToArray());
|
||||
|
||||
var prompt = "Extract the recipe from this image. Return Title and Description.";
|
||||
|
||||
// 1. Initialize Content with the Role in the constructor
|
||||
var content = new Content(Role.User);
|
||||
|
||||
// 2. Assign the parts using dynamic to bypass the IPart/Part conversion headache
|
||||
content.Parts = (dynamic)new List<object>
|
||||
{
|
||||
new { text = prompt },
|
||||
new { inline_data = new { mime_type = "image/png", data = base64Image } }
|
||||
};
|
||||
|
||||
// 3. Create the request
|
||||
var request = new GenerateContentRequest
|
||||
{
|
||||
Contents = new List<Content> { content }
|
||||
};
|
||||
|
||||
// 4. Call the model
|
||||
var response = await model.GenerateContent(request);
|
||||
|
||||
return new RecipeResponseDto
|
||||
{
|
||||
Title = "Gemini 2.5 Analysis",
|
||||
Description = response.Text ?? "No text returned",
|
||||
Ingredients = new List<string>(),
|
||||
Instructions = new List<string>()
|
||||
};
|
||||
}
|
||||
}
|
||||
49
.vscode-server/data/User/History/b03096/2oaa.cs
Normal file
49
.vscode-server/data/User/History/b03096/2oaa.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using Seasoned.Backend.DTOs;
|
||||
using Mscc.GenerativeAI;
|
||||
|
||||
namespace Seasoned.Backend.Services;
|
||||
|
||||
public class RecipeService : IRecipeService
|
||||
{
|
||||
private readonly string _apiKey;
|
||||
|
||||
public RecipeService(IConfiguration config)
|
||||
{
|
||||
_apiKey = config["GeminiApiKey"] ?? throw new ArgumentNullException("API Key missing");
|
||||
}
|
||||
|
||||
public async Task<RecipeResponseDto> ParseRecipeImageAsync(IFormFile image)
|
||||
{
|
||||
var googleAI = new GoogleAI(_apiKey);
|
||||
var model = googleAI.GenerativeModel("gemini-2.5-flash");
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
await image.CopyToAsync(ms);
|
||||
var base64Image = Convert.ToBase64String(ms.ToArray());
|
||||
|
||||
var prompt = "Extract the recipe from this image. Return Title and Description.";
|
||||
|
||||
var content = new Content(Role.User);
|
||||
|
||||
content.Parts = new List<IPart>
|
||||
{
|
||||
(IPart)new Part { Text = prompt },
|
||||
(IPart)new Part { InlineData = new InlineData { MimeType = "image/png", Data = base64Image } }
|
||||
};
|
||||
|
||||
var request = new GenerateContentRequest
|
||||
{
|
||||
Contents = new List<Content> { content }
|
||||
};
|
||||
|
||||
var response = await model.GenerateContent(request);
|
||||
|
||||
return new RecipeResponseDto
|
||||
{
|
||||
Title = "Gemini 2.5 Analysis",
|
||||
Description = response.Text ?? "No text returned",
|
||||
Ingredients = new List<string>(),
|
||||
Instructions = new List<string>()
|
||||
};
|
||||
}
|
||||
}
|
||||
48
.vscode-server/data/User/History/b03096/4GWQ.cs
Normal file
48
.vscode-server/data/User/History/b03096/4GWQ.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using Seasoned.Backend.DTOs;
|
||||
using Mscc.GenerativeAI;
|
||||
|
||||
namespace Seasoned.Backend.Services;
|
||||
|
||||
public class RecipeService : IRecipeService
|
||||
{
|
||||
private readonly string _apiKey;
|
||||
|
||||
public RecipeService(IConfiguration config)
|
||||
{
|
||||
_apiKey = config["GeminiApiKey"] ?? throw new ArgumentNullException("API Key missing");
|
||||
}
|
||||
|
||||
public async Task<RecipeResponseDto> ParseRecipeImageAsync(IFormFile image)
|
||||
{
|
||||
var googleAI = new GoogleAI(_apiKey);
|
||||
var model = googleAI.GenerativeModel("gemini-2.5-flash");
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
await image.CopyToAsync(ms);
|
||||
var base64Image = Convert.ToBase64String(ms.ToArray());
|
||||
|
||||
var prompt = "Extract the recipe from this image. Return Title and Description.";
|
||||
|
||||
var content = new Content(Role.User);
|
||||
|
||||
content.Parts = new List<IPart>
|
||||
{
|
||||
(IPart)new Part { Text = prompt },
|
||||
(IPart)new Part { InlineData = new InlineData { MimeType = "image/png", Data = base64Image } }
|
||||
};
|
||||
|
||||
var request = new GenerateContentRequest
|
||||
{
|
||||
Contents = new List<Content> { content }
|
||||
};
|
||||
|
||||
var response = await model.GenerateContent(request);
|
||||
|
||||
return new RecipeResponseDto
|
||||
{
|
||||
Title = "Gemini 2.5 Analysis",
|
||||
Description = response.Text ?? "No text returned",
|
||||
Ingredients = new List<string>(),
|
||||
Instructions = new List<string>()
|
||||
};
|
||||
}
|
||||
18
.vscode-server/data/User/History/b03096/77Sz.cs
Normal file
18
.vscode-server/data/User/History/b03096/77Sz.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using Seasoned.Backend.DTOs;
|
||||
|
||||
namespace Seasoned.Backend.Services;
|
||||
|
||||
public class RecipeService : IRecipeService
|
||||
{
|
||||
public async Task<RecipeResponseDto> ParseRecipeImageAsync(IFormFile image)
|
||||
{
|
||||
// Placeholder logic to satisfy the return type
|
||||
return new RecipeResponseDto
|
||||
{
|
||||
Title = "Mock Recipe",
|
||||
Description = "This is a placeholder until Gemini is linked.",
|
||||
Ingredients = new List<string> { "Ingredient A", "Ingredient B" },
|
||||
Instructions = new List<string> { "Cook it", "Eat it" }
|
||||
};
|
||||
}
|
||||
}
|
||||
43
.vscode-server/data/User/History/b03096/BJsp.cs
Normal file
43
.vscode-server/data/User/History/b03096/BJsp.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using Seasoned.Backend.DTOs;
|
||||
using Mscc.GenerativeAI;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System.IO;
|
||||
|
||||
namespace Seasoned.Backend.Services;
|
||||
|
||||
public class RecipeService : IRecipeService
|
||||
{
|
||||
private readonly string _apiKey;
|
||||
|
||||
public RecipeService(IConfiguration config)
|
||||
{
|
||||
_apiKey = config["GeminiApiKey"] ?? throw new ArgumentNullException("API Key missing");
|
||||
}
|
||||
|
||||
public async Task<RecipeResponseDto> ParseRecipeImageAsync(IFormFile image)
|
||||
{
|
||||
var googleAI = new GoogleAI(_apiKey);
|
||||
var model = googleAI.GenerativeModel("gemini-2.5-flash");
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
await image.CopyToAsync(ms);
|
||||
|
||||
var base64Image = Convert.ToBase64String(ms.ToArray());
|
||||
|
||||
var prompt = "Extract the recipe from this image. Return Title and Description.";
|
||||
|
||||
var request = new GenerateContentRequest(prompt);
|
||||
|
||||
await request.AddMedia(base64Image, "image/png");
|
||||
|
||||
var response = await model.GenerateContent(request);
|
||||
|
||||
return new RecipeResponseDto
|
||||
{
|
||||
Title = "Gemini 2.5 Analysis",
|
||||
Description = response.Text ?? "No text returned",
|
||||
Ingredients = new List<string>(),
|
||||
Instructions = new List<string>()
|
||||
};
|
||||
}
|
||||
}
|
||||
50
.vscode-server/data/User/History/b03096/DZeF.cs
Normal file
50
.vscode-server/data/User/History/b03096/DZeF.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using Seasoned.Backend.DTOs;
|
||||
using Mscc.GenerativeAI;
|
||||
|
||||
namespace Seasoned.Backend.Services;
|
||||
|
||||
public class RecipeService : IRecipeService
|
||||
{
|
||||
private readonly string _apiKey;
|
||||
|
||||
public RecipeService(IConfiguration config)
|
||||
{
|
||||
_apiKey = config["GeminiApiKey"] ?? throw new ArgumentNullException("API Key missing");
|
||||
}
|
||||
|
||||
public async Task<RecipeResponseDto> ParseRecipeImageAsync(IFormFile image)
|
||||
{
|
||||
var googleAI = new GoogleAI(_apiKey);
|
||||
var model = googleAI.GenerativeModel("gemini-2.5-flash");
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
await image.CopyToAsync(ms);
|
||||
var base64Image = Convert.ToBase64String(ms.ToArray());
|
||||
|
||||
var prompt = "Extract the recipe from this image. Return Title and Description.";
|
||||
|
||||
var parts = new List<IPart>
|
||||
{
|
||||
new Part { Text = prompt },
|
||||
new Part { InlineData = new InlineData { MimeType = "image/png", Data = base64Image } }
|
||||
};
|
||||
|
||||
var content = new Content(parts);
|
||||
content.Role = Role.User;
|
||||
|
||||
var request = new GenerateContentRequest
|
||||
{
|
||||
Contents = new List<Content> { content }
|
||||
};
|
||||
|
||||
var response = await model.GenerateContent(request);
|
||||
|
||||
return new RecipeResponseDto
|
||||
{
|
||||
Title = "Gemini 2.5 Analysis",
|
||||
Description = response.Text ?? "No text returned",
|
||||
Ingredients = new List<string>(),
|
||||
Instructions = new List<string>()
|
||||
};
|
||||
}
|
||||
}
|
||||
49
.vscode-server/data/User/History/b03096/GoWQ.cs
Normal file
49
.vscode-server/data/User/History/b03096/GoWQ.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using Seasoned.Backend.DTOs;
|
||||
using Mscc.GenerativeAI;
|
||||
|
||||
namespace Seasoned.Backend.Services;
|
||||
|
||||
public class RecipeService : IRecipeService
|
||||
{
|
||||
private readonly string _apiKey;
|
||||
|
||||
public RecipeService(IConfiguration config)
|
||||
{
|
||||
_apiKey = config["GeminiApiKey"] ?? throw new ArgumentNullException("API Key missing");
|
||||
}
|
||||
|
||||
public async Task<RecipeResponseDto> ParseRecipeImageAsync(IFormFile image)
|
||||
{
|
||||
var googleAI = new GoogleAI(_apiKey);
|
||||
var model = googleAI.GenerativeModel("gemini-2.5-flash");
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
await image.CopyToAsync(ms);
|
||||
var base64Image = Convert.ToBase64String(ms.ToArray());
|
||||
|
||||
var prompt = "Extract the recipe from this image. Return Title and Description.";
|
||||
|
||||
var content = new Content(Role.User);
|
||||
|
||||
content.Parts = new List<IPart>
|
||||
{
|
||||
(IPart)new Part { Text = prompt },
|
||||
(IPart)new Part { InlineData = new InlineData { MimeType = "image/png", Data = base64Image } }
|
||||
};
|
||||
|
||||
var request = new GenerateContentRequest
|
||||
{
|
||||
Contents = new List<Content> { content }
|
||||
};
|
||||
|
||||
var response = await model.GenerateContent(request);
|
||||
|
||||
return new RecipeResponseDto
|
||||
{
|
||||
Title = "Gemini 2.5 Analysis",
|
||||
Description = response.Text ?? "No text returned",
|
||||
Ingredients = new List<string>(),
|
||||
Instructions = new List<string>()
|
||||
};
|
||||
}
|
||||
}
|
||||
52
.vscode-server/data/User/History/b03096/Goe4.cs
Normal file
52
.vscode-server/data/User/History/b03096/Goe4.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using Seasoned.Backend.DTOs;
|
||||
using Mscc.GenerativeAI;
|
||||
|
||||
namespace Seasoned.Backend.Services;
|
||||
|
||||
public class RecipeService : IRecipeService
|
||||
{
|
||||
private readonly string _apiKey;
|
||||
|
||||
public RecipeService(IConfiguration config)
|
||||
{
|
||||
_apiKey = config["GeminiApiKey"] ?? throw new ArgumentNullException("API Key missing");
|
||||
}
|
||||
|
||||
public async Task<RecipeResponseDto> ParseRecipeImageAsync(IFormFile image)
|
||||
{
|
||||
// Use the explicit string for the model to bypass the "Model.Gemini25Flash" error
|
||||
var googleAI = new GoogleAI(_apiKey);
|
||||
var model = googleAI.GenerativeModel("gemini-2.5-flash");
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
await image.CopyToAsync(ms);
|
||||
var base64Image = Convert.ToBase64String(ms.ToArray());
|
||||
|
||||
// Use a dynamic request structure which the library supports for newer models
|
||||
var prompt = "Extract the recipe from this image. Return Title and Description.";
|
||||
|
||||
// This is a more robust way to send the request in the latest version
|
||||
var response = await model.GenerateContent(new()
|
||||
{
|
||||
Contents = new List<Content>
|
||||
{
|
||||
new Content
|
||||
{
|
||||
Parts = new List<Part>
|
||||
{
|
||||
new() { Text = prompt },
|
||||
new() { InlineData = new InlineData { MimeType = "image/png", Data = base64Image } }
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return new RecipeResponseDto
|
||||
{
|
||||
Title = "Gemini 2.5 Analysis",
|
||||
Description = response.Text ?? "No text returned",
|
||||
Ingredients = new List<string>(),
|
||||
Instructions = new List<string>()
|
||||
};
|
||||
}
|
||||
}
|
||||
52
.vscode-server/data/User/History/b03096/Gr2p.cs
Normal file
52
.vscode-server/data/User/History/b03096/Gr2p.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using Seasoned.Backend.DTOs;
|
||||
using Mscc.GenerativeAI;
|
||||
|
||||
namespace Seasoned.Backend.Services;
|
||||
|
||||
public class RecipeService : IRecipeService
|
||||
{
|
||||
private readonly string _apiKey;
|
||||
|
||||
public RecipeService(IConfiguration config)
|
||||
{
|
||||
_apiKey = config["GeminiApiKey"] ?? throw new ArgumentNullException("API Key missing");
|
||||
}
|
||||
|
||||
public async Task<RecipeResponseDto> ParseRecipeImageAsync(IFormFile image)
|
||||
{
|
||||
var googleAI = new GoogleAI(_apiKey);
|
||||
var model = googleAI.GenerativeModel("gemini-2.5-flash");
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
await image.CopyToAsync(ms);
|
||||
var base64Image = Convert.ToBase64String(ms.ToArray());
|
||||
|
||||
var prompt = "Extract the recipe from this image. Return Title and Description.";
|
||||
|
||||
// Use the constructor that the error message suggested: Content(string role)
|
||||
var content = new Content(Role.User);
|
||||
|
||||
// Add parts manually to avoid the IPart/Part conversion headache
|
||||
content.Parts = new List<Part>
|
||||
{
|
||||
new Part { Text = prompt },
|
||||
new Part { InlineData = new InlineData { MimeType = "image/png", Data = base64Image } }
|
||||
};
|
||||
|
||||
var request = new GenerateContentRequest
|
||||
{
|
||||
Contents = new List<Content> { content }
|
||||
};
|
||||
|
||||
// Call the model with the explicit request
|
||||
var response = await model.GenerateContent(request);
|
||||
|
||||
return new RecipeResponseDto
|
||||
{
|
||||
Title = "Gemini 2.5 Analysis",
|
||||
Description = response.Text ?? "No text returned",
|
||||
Ingredients = new List<string>(),
|
||||
Instructions = new List<string>()
|
||||
};
|
||||
}
|
||||
}
|
||||
55
.vscode-server/data/User/History/b03096/J28Z.cs
Normal file
55
.vscode-server/data/User/History/b03096/J28Z.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using Seasoned.Backend.DTOs;
|
||||
using Mscc.GenerativeAI;
|
||||
|
||||
namespace Seasoned.Backend.Services;
|
||||
|
||||
public class RecipeService : IRecipeService
|
||||
{
|
||||
private readonly string _apiKey;
|
||||
|
||||
public RecipeService(IConfiguration config)
|
||||
{
|
||||
_apiKey = config["GeminiApiKey"] ?? throw new ArgumentNullException("API Key missing");
|
||||
}
|
||||
|
||||
public async Task<RecipeResponseDto> ParseRecipeImageAsync(IFormFile image)
|
||||
{
|
||||
var googleAI = new Mscc.GenerativeAI.GoogleAI(_apiKey);
|
||||
|
||||
// Explicitly calling Gemini 2.5 Flash
|
||||
var model = googleAI.GenerativeModel(Mscc.GenerativeAI.Model.Gemini25Flash);
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
await image.CopyToAsync(ms);
|
||||
var base64Image = Convert.ToBase64String(ms.ToArray());
|
||||
|
||||
var prompt = "Extract the recipe from this image. Return Title and Description.";
|
||||
|
||||
// Using full namespace paths for all request objects
|
||||
var request = new Mscc.GenerativeAI.GenerateContentRequest
|
||||
{
|
||||
Contents = new List<Mscc.GenerativeAI.Content>
|
||||
{
|
||||
new Mscc.GenerativeAI.Content
|
||||
{
|
||||
Role = Mscc.GenerativeAI.Role.User,
|
||||
Parts = new List<Mscc.GenerativeAI.Part>
|
||||
{
|
||||
new Mscc.GenerativeAI.TextPart { Text = prompt },
|
||||
new Mscc.GenerativeAI.InlineDataPart { MimeType = "image/png", Data = base64Image }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var response = await model.GenerateContent(request);
|
||||
|
||||
return new RecipeResponseDto
|
||||
{
|
||||
Title = "Gemini 2.5 Result",
|
||||
Description = response.Text ?? "No text returned",
|
||||
Ingredients = new List<string>(),
|
||||
Instructions = new List<string>()
|
||||
};
|
||||
}
|
||||
}
|
||||
47
.vscode-server/data/User/History/b03096/MbC8.cs
Normal file
47
.vscode-server/data/User/History/b03096/MbC8.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using Seasoned.Backend.DTOs;
|
||||
using Mscc.GenerativeAI;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System.IO;
|
||||
|
||||
namespace Seasoned.Backend.Services;
|
||||
|
||||
public class RecipeService : IRecipeService
|
||||
{
|
||||
private readonly string _apiKey;
|
||||
|
||||
public RecipeService(IConfiguration config)
|
||||
{
|
||||
_apiKey = config["GeminiApiKey"] ?? throw new ArgumentNullException("API Key missing");
|
||||
}
|
||||
|
||||
public async Task<RecipeResponseDto> ParseRecipeImageAsync(IFormFile image)
|
||||
{
|
||||
var googleAI = new GoogleAI(_apiKey);
|
||||
// Using the 2026 model string
|
||||
var model = googleAI.GenerativeModel("gemini-2.5-flash");
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
await image.CopyToAsync(ms);
|
||||
var imageBytes = ms.ToArray();
|
||||
|
||||
var prompt = "Extract the recipe from this image. Return Title and Description.";
|
||||
|
||||
// 1. New GenerateContentRequest automatically handles the text
|
||||
var request = new GenerateContentRequest(prompt);
|
||||
|
||||
// 2. AddMedia is now the standard for version 3.x+
|
||||
// This handles the binary-to-base64 conversion internally!
|
||||
request.AddMedia(imageBytes, "image/png");
|
||||
|
||||
// 3. Send the unified request
|
||||
var response = await model.GenerateContent(request);
|
||||
|
||||
return new RecipeResponseDto
|
||||
{
|
||||
Title = "Gemini 2.5 Analysis",
|
||||
Description = response.Text ?? "No text returned",
|
||||
Ingredients = new List<string>(),
|
||||
Instructions = new List<string>()
|
||||
};
|
||||
}
|
||||
}
|
||||
49
.vscode-server/data/User/History/b03096/Smgs.cs
Normal file
49
.vscode-server/data/User/History/b03096/Smgs.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using Seasoned.Backend.DTOs;
|
||||
using Mscc.GenerativeAI;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System.IO;
|
||||
|
||||
namespace Seasoned.Backend.Services;
|
||||
|
||||
public class RecipeService : IRecipeService
|
||||
{
|
||||
private readonly string _apiKey;
|
||||
|
||||
public RecipeService(IConfiguration config)
|
||||
{
|
||||
_apiKey = config["GeminiApiKey"] ?? throw new ArgumentNullException("API Key missing");
|
||||
}
|
||||
|
||||
public async Task<RecipeResponseDto> ParseRecipeImageAsync(IFormFile image)
|
||||
{
|
||||
var googleAI = new GoogleAI(_apiKey);
|
||||
var model = googleAI.GenerativeModel("gemini-2.5-flash");
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
await image.CopyToAsync(ms);
|
||||
var base64Image = Convert.ToBase64String(ms.ToArray());
|
||||
|
||||
// 1. Better Prompt: Tell Gemini exactly what the JSON should look like
|
||||
var prompt = @"Extract the recipe from this image.
|
||||
Return a JSON object with exactly these fields:
|
||||
{
|
||||
""title"": ""string"",
|
||||
""description"": ""string"",
|
||||
""ingredients"": [""string""],
|
||||
""instructions"": [""string""]
|
||||
}";
|
||||
|
||||
// 2. Set the Response MIME Type to application/json
|
||||
var config = new GenerationConfig { ResponseMimeType = "application/json" };
|
||||
var request = new GenerateContentRequest(prompt, config);
|
||||
request.AddMedia(base64Image, "image/png");
|
||||
|
||||
var response = await model.GenerateContent(request);
|
||||
|
||||
// 3. Use System.Text.Json to turn that string back into our DTO
|
||||
var options = new System.Text.Json.JsonSerializerOptions { PropertyNameCaseInsensitive = true };
|
||||
var result = System.Text.Json.JsonSerializer.Deserialize<RecipeResponseDto>(response.Text, options);
|
||||
|
||||
return result ?? new RecipeResponseDto { Title = "Error parsing JSON" };
|
||||
}
|
||||
}
|
||||
50
.vscode-server/data/User/History/b03096/Tt28.cs
Normal file
50
.vscode-server/data/User/History/b03096/Tt28.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using Seasoned.Backend.DTOs;
|
||||
using Mscc.GenerativeAI;
|
||||
|
||||
namespace Seasoned.Backend.Services;
|
||||
|
||||
public class RecipeService : IRecipeService
|
||||
{
|
||||
private readonly string _apiKey;
|
||||
|
||||
public RecipeService(IConfiguration config)
|
||||
{
|
||||
_apiKey = config["GeminiApiKey"] ?? throw new ArgumentNullException("API Key missing");
|
||||
}
|
||||
|
||||
public async Task<RecipeResponseDto> ParseRecipeImageAsync(IFormFile image)
|
||||
{
|
||||
var googleAI = new GoogleAI(_apiKey);
|
||||
var model = googleAI.GenerativeModel("gemini-2.5-flash");
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
await image.CopyToAsync(ms);
|
||||
var base64Image = Convert.ToBase64String(ms.ToArray());
|
||||
|
||||
var prompt = "Extract the recipe from this image. Return Title and Description.";
|
||||
|
||||
// Use the library's internal GenerateContentRequest but manually build the Parts list
|
||||
var request = new GenerateContentRequest();
|
||||
var content = new Content(Role.User);
|
||||
|
||||
// This is the specific syntax to satisfy the IPart list requirement
|
||||
content.Parts = new List<IPart>
|
||||
{
|
||||
new Part { Text = prompt },
|
||||
new Part { InlineData = new InlineData { MimeType = "image/png", Data = base64Image } }
|
||||
}.Cast<IPart>().ToList(); // This 'Cast' is the magic bullet
|
||||
|
||||
request.Contents = new List<Content> { content };
|
||||
|
||||
// Solve the ambiguity by picking the Request overload
|
||||
var response = await model.GenerateContent(request);
|
||||
|
||||
return new RecipeResponseDto
|
||||
{
|
||||
Title = "Gemini 2.5 Analysis",
|
||||
Description = response.Text ?? "No text returned",
|
||||
Ingredients = new List<string>(),
|
||||
Instructions = new List<string>()
|
||||
};
|
||||
}
|
||||
}
|
||||
56
.vscode-server/data/User/History/b03096/WeNg.cs
Normal file
56
.vscode-server/data/User/History/b03096/WeNg.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using Seasoned.Backend.DTOs;
|
||||
using Mscc.GenerativeAI;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System.IO;
|
||||
|
||||
namespace Seasoned.Backend.Services;
|
||||
|
||||
public class RecipeService : IRecipeService
|
||||
{
|
||||
private readonly string _apiKey;
|
||||
|
||||
public RecipeService(IConfiguration config)
|
||||
{
|
||||
_apiKey = config["GeminiApiKey"] ?? throw new ArgumentNullException("API Key missing");
|
||||
}
|
||||
|
||||
public async Task<RecipeResponseDto> ParseRecipeImageAsync(IFormFile image)
|
||||
{
|
||||
var googleAI = new GoogleAI(_apiKey);
|
||||
// Use a string for the model name to avoid CS0117
|
||||
var model = googleAI.GenerativeModel("gemini-2.5-flash");
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
await image.CopyToAsync(ms);
|
||||
var base64Image = Convert.ToBase64String(ms.ToArray());
|
||||
|
||||
var prompt = "Extract the recipe from this image. Return Title and Description.";
|
||||
|
||||
// Use the constructor that the library likes
|
||||
var request = new GenerateContentRequest();
|
||||
|
||||
// Manually build the structure in a way that avoids the List conversion crash
|
||||
var content = new Content(Role.User);
|
||||
|
||||
// We add the text part using the library's preferred text-first approach
|
||||
request.Contents = new List<Content> { content };
|
||||
|
||||
// Attempting the most universal "Add" method for media
|
||||
// If your library doesn't have AddMedia, we use this direct property:
|
||||
content.Parts = new List<IPart>
|
||||
{
|
||||
new TextPart(prompt),
|
||||
new InlineDataPart("image/png", base64Image)
|
||||
};
|
||||
|
||||
var response = await model.GenerateContent(request);
|
||||
|
||||
return new RecipeResponseDto
|
||||
{
|
||||
Title = "Gemini 2.5 Analysis",
|
||||
Description = response.Text ?? "No text returned",
|
||||
Ingredients = new List<string>(),
|
||||
Instructions = new List<string>()
|
||||
};
|
||||
}
|
||||
}
|
||||
47
.vscode-server/data/User/History/b03096/XLsh.cs
Normal file
47
.vscode-server/data/User/History/b03096/XLsh.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using Seasoned.Backend.DTOs;
|
||||
using Mscc.GenerativeAI; // Add this!
|
||||
|
||||
namespace Seasoned.Backend.Services;
|
||||
|
||||
public class RecipeService : IRecipeService
|
||||
{
|
||||
private readonly string _apiKey;
|
||||
|
||||
public RecipeService(IConfiguration config)
|
||||
{
|
||||
// Get the key from your user-secrets
|
||||
_apiKey = config["GeminiApiKey"] ?? throw new ArgumentNullException("API Key missing");
|
||||
}
|
||||
|
||||
public async Task<RecipeResponseDto> ParseRecipeImageAsync(IFormFile image)
|
||||
{
|
||||
// 1. Initialize Gemini
|
||||
var googleAI = new GoogleAI(_apiKey);
|
||||
var model = googleAI.GenerativeModel(Model.Gemini15Flash);
|
||||
|
||||
// 2. Convert the uploaded image to a format Gemini understands
|
||||
using var ms = new MemoryStream();
|
||||
await image.CopyToAsync(ms);
|
||||
var base64Image = Convert.ToBase64String(ms.ToArray());
|
||||
|
||||
// 3. The "Magic" Prompt
|
||||
var prompt = "Extract the recipe from this image. Return ONLY a JSON object with: title (string), description (string), ingredients (array of strings), and instructions (array of strings).";
|
||||
|
||||
// 4. Call Gemini
|
||||
var response = await model.GenerateContent(new List<Part> {
|
||||
new TextPart { Text = prompt },
|
||||
new InlineDataPart { MimeType = "image/jpeg", Data = base64Image }
|
||||
});
|
||||
|
||||
// 5. Parse the AI's response (simplified for now)
|
||||
var aiText = response.Text;
|
||||
|
||||
// For now, let's return the AI text in our DTO
|
||||
return new RecipeResponseDto
|
||||
{
|
||||
Title = "AI Decoded Recipe",
|
||||
Description = aiText, // The raw AI response
|
||||
Ingredients = new List<string> { "Check description for details" }
|
||||
};
|
||||
}
|
||||
}
|
||||
53
.vscode-server/data/User/History/b03096/ZxdS.cs
Normal file
53
.vscode-server/data/User/History/b03096/ZxdS.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using Seasoned.Backend.DTOs;
|
||||
using Mscc.GenerativeAI;
|
||||
|
||||
namespace Seasoned.Backend.Services;
|
||||
|
||||
public class RecipeService : IRecipeService
|
||||
{
|
||||
private readonly string _apiKey;
|
||||
|
||||
public RecipeService(IConfiguration config)
|
||||
{
|
||||
_apiKey = config["GeminiApiKey"] ?? throw new ArgumentNullException("API Key missing");
|
||||
}
|
||||
|
||||
public async Task<RecipeResponseDto> ParseRecipeImageAsync(IFormFile image)
|
||||
{
|
||||
var googleAI = new GoogleAI(_apiKey);
|
||||
var model = googleAI.GenerativeModel("gemini-2.5-flash");
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
await image.CopyToAsync(ms);
|
||||
var base64Image = Convert.ToBase64String(ms.ToArray());
|
||||
|
||||
var prompt = "Extract the recipe from this image. Return Title and Description.";
|
||||
|
||||
// 1. Create the parts using the IPart interface
|
||||
var parts = new List<IPart>
|
||||
{
|
||||
new TextPart { Text = prompt },
|
||||
new InlineDataPart { MimeType = "image/png", Data = base64Image }
|
||||
};
|
||||
|
||||
// 2. Create Content using the constructor (to fix CS1729)
|
||||
var content = new Content(parts, Role.User);
|
||||
|
||||
// 3. Create the Request
|
||||
var request = new GenerateContentRequest
|
||||
{
|
||||
Contents = new List<Content> { content }
|
||||
};
|
||||
|
||||
// 4. Call the model
|
||||
var response = await model.GenerateContent(request);
|
||||
|
||||
return new RecipeResponseDto
|
||||
{
|
||||
Title = "Gemini 2.5 Analysis",
|
||||
Description = response.Text ?? "No text returned",
|
||||
Ingredients = new List<string>(),
|
||||
Instructions = new List<string>()
|
||||
};
|
||||
}
|
||||
}
|
||||
24
.vscode-server/data/User/History/b03096/dXqj.cs
Normal file
24
.vscode-server/data/User/History/b03096/dXqj.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using Seasoned.Backend.DTOs;
|
||||
|
||||
namespace Seasoned.Backend.Services;
|
||||
|
||||
public interface IRecipeService
|
||||
{
|
||||
Task<RecipeResponseDto> ParseRecipeImageAsync(IFormFile image);
|
||||
}
|
||||
|
||||
public class RecipeService : IRecipeService
|
||||
{
|
||||
public async Task<RecipeResponseDto> ParseRecipeImageAsync(IFormFile image)
|
||||
{
|
||||
// For now, this is a "Mock" service.
|
||||
// Later, we will add the Gemini API call here.
|
||||
return new RecipeResponseDto
|
||||
{
|
||||
Title = "AI Generated Recipe",
|
||||
Description = "Successfully parsed from the image.",
|
||||
Ingredients = new List<string> { "Example Ingredient 1", "Example Ingredient 2" },
|
||||
Instructions = new List<string> { "Step 1: Mix everything", "Step 2: Cook it" }
|
||||
};
|
||||
}
|
||||
}
|
||||
57
.vscode-server/data/User/History/b03096/dZC4.cs
Normal file
57
.vscode-server/data/User/History/b03096/dZC4.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using Seasoned.Backend.DTOs;
|
||||
using Mscc.GenerativeAI;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System.IO;
|
||||
|
||||
namespace Seasoned.Backend.Services;
|
||||
|
||||
public class RecipeService : IRecipeService
|
||||
{
|
||||
private readonly string _apiKey;
|
||||
|
||||
public RecipeService(IConfiguration config)
|
||||
{
|
||||
_apiKey = config["GeminiApiKey"] ?? throw new ArgumentNullException("API Key missing");
|
||||
}
|
||||
|
||||
public async Task<RecipeResponseDto> ParseRecipeImageAsync(IFormFile image)
|
||||
{
|
||||
var googleAI = new GoogleAI(_apiKey);
|
||||
var model = googleAI.GenerativeModel("gemini-2.5-flash");
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
await image.CopyToAsync(ms);
|
||||
var base64Image = Convert.ToBase64String(ms.ToArray());
|
||||
|
||||
var prompt = "Extract the recipe from this image. Return Title and Description.";
|
||||
|
||||
// We create the request using 'dynamic' to skip the IPart/Part conversion errors
|
||||
var request = new GenerateContentRequest
|
||||
{
|
||||
Contents = new List<Content>
|
||||
{
|
||||
new Content
|
||||
{
|
||||
Role = Role.User,
|
||||
// We cast the list to dynamic so the compiler doesn't check the 'Part' types
|
||||
Parts = (dynamic)new List<object>
|
||||
{
|
||||
new { text = prompt },
|
||||
new { inline_data = new { mime_type = "image/png", data = base64Image } }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Call the model with our request
|
||||
var response = await model.GenerateContent(request);
|
||||
|
||||
return new RecipeResponseDto
|
||||
{
|
||||
Title = "Gemini 2.5 Analysis",
|
||||
Description = response.Text ?? "No text returned",
|
||||
Ingredients = new List<string>(),
|
||||
Instructions = new List<string>()
|
||||
};
|
||||
}
|
||||
}
|
||||
52
.vscode-server/data/User/History/b03096/dxLf.cs
Normal file
52
.vscode-server/data/User/History/b03096/dxLf.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using Seasoned.Backend.DTOs;
|
||||
using Mscc.GenerativeAI;
|
||||
|
||||
namespace Seasoned.Backend.Services;
|
||||
|
||||
public class RecipeService : IRecipeService
|
||||
{
|
||||
private readonly string _apiKey;
|
||||
|
||||
public RecipeService(IConfiguration config)
|
||||
{
|
||||
_apiKey = config["GeminiApiKey"] ?? throw new ArgumentNullException("API Key missing");
|
||||
}
|
||||
|
||||
public async Task<RecipeResponseDto> ParseRecipeImageAsync(IFormFile image)
|
||||
{
|
||||
var googleAI = new GoogleAI(_apiKey);
|
||||
var model = googleAI.GenerativeModel("gemini-2.5-flash");
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
await image.CopyToAsync(ms);
|
||||
var base64Image = Convert.ToBase64String(ms.ToArray());
|
||||
|
||||
var prompt = "Extract the recipe from this image. Return Title and Description.";
|
||||
|
||||
// Explicitly typed request object
|
||||
GenerateContentRequest request = new()
|
||||
{
|
||||
Contents = new List<Content>
|
||||
{
|
||||
new Content
|
||||
{
|
||||
Parts = new List<Part>
|
||||
{
|
||||
new() { Text = prompt },
|
||||
new() { InlineData = new InlineData { MimeType = "image/png", Data = base64Image } }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var response = await model.GenerateContent((GenerateContentRequest)request);
|
||||
|
||||
return new RecipeResponseDto
|
||||
{
|
||||
Title = "Gemini 2.5 Analysis",
|
||||
Description = response.Text ?? "No text returned",
|
||||
Ingredients = new List<string>(),
|
||||
Instructions = new List<string>()
|
||||
};
|
||||
}
|
||||
}
|
||||
1
.vscode-server/data/User/History/b03096/entries.json
Normal file
1
.vscode-server/data/User/History/b03096/entries.json
Normal file
@@ -0,0 +1 @@
|
||||
{"version":1,"resource":"vscode-remote://ssh-remote%2B10.0.11.3/home/chloe/Seasoned.Backend/Services/RecipeService.cs","entries":[{"id":"dXqj.cs","timestamp":1772653693352},{"id":"77Sz.cs","timestamp":1772653852608},{"id":"XLsh.cs","timestamp":1772655862562},{"id":"vh2Y.cs","timestamp":1772657163089},{"id":"J28Z.cs","timestamp":1772657199088},{"id":"Goe4.cs","timestamp":1772657272583},{"id":"dxLf.cs","timestamp":1772657432564},{"id":"r1gL.cs","timestamp":1772657455148},{"id":"ZxdS.cs","timestamp":1772657509246},{"id":"sqBf.cs","timestamp":1772657543478},{"id":"DZeF.cs","timestamp":1772657595090},{"id":"Gr2p.cs","timestamp":1772657644181},{"id":"2oaa.cs","timestamp":1772657722505},{"id":"4GWQ.cs","timestamp":1772657735239},{"id":"GoWQ.cs","timestamp":1772657762861},{"id":"euIa.cs","timestamp":1772658484116},{"id":"Tt28.cs","timestamp":1772659259080},{"id":"y3ZY.cs","timestamp":1772659286185},{"id":"ik8E.cs","timestamp":1772659373055},{"id":"dZC4.cs","timestamp":1772659424718},{"id":"26Rk.cs","timestamp":1772659464758},{"id":"yxfK.cs","timestamp":1772659765699},{"id":"WeNg.cs","timestamp":1772659813242},{"id":"MbC8.cs","timestamp":1772659856530},{"id":"gr1X.cs","timestamp":1772659909009},{"id":"BJsp.cs","timestamp":1772660249541},{"id":"Smgs.cs","timestamp":1772660613374}]}
|
||||
51
.vscode-server/data/User/History/b03096/euIa.cs
Normal file
51
.vscode-server/data/User/History/b03096/euIa.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using Seasoned.Backend.DTOs;
|
||||
using Mscc.GenerativeAI;
|
||||
|
||||
namespace Seasoned.Backend.Services;
|
||||
|
||||
public class RecipeService : IRecipeService
|
||||
{
|
||||
private readonly string _apiKey;
|
||||
|
||||
public RecipeService(IConfiguration config)
|
||||
{
|
||||
_apiKey = config["GeminiApiKey"] ?? throw new ArgumentNullException("API Key missing");
|
||||
}
|
||||
|
||||
public async Task<RecipeResponseDto> ParseRecipeImageAsync(IFormFile image)
|
||||
{
|
||||
var googleAI = new GoogleAI(_apiKey);
|
||||
var model = googleAI.GenerativeModel("gemini-2.5-flash");
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
await image.CopyToAsync(ms);
|
||||
var base64Image = Convert.ToBase64String(ms.ToArray());
|
||||
|
||||
var prompt = "Extract the recipe from this image. Return Title and Description.";
|
||||
|
||||
// We create the request using the library's internal 'Content' structure
|
||||
// but we add the parts as simple objects to avoid the IPart cast crash.
|
||||
var content = new Content(Role.User);
|
||||
content.Parts = new List<IPart>();
|
||||
|
||||
// Instead of 'new Part', we use the specific Part types provided by the library
|
||||
// that are GUARANTEED to implement IPart correctly.
|
||||
content.Parts.Add(new TextPart { Text = prompt });
|
||||
content.Parts.Add(new InlineDataPart { MimeType = "image/png", Data = base64Image });
|
||||
|
||||
var request = new GenerateContentRequest
|
||||
{
|
||||
Contents = new List<Content> { content }
|
||||
};
|
||||
|
||||
var response = await model.GenerateContent(request);
|
||||
|
||||
return new RecipeResponseDto
|
||||
{
|
||||
Title = "Gemini 2.5 Analysis",
|
||||
Description = response.Text ?? "No text returned",
|
||||
Ingredients = new List<string>(),
|
||||
Instructions = new List<string>()
|
||||
};
|
||||
}
|
||||
}
|
||||
45
.vscode-server/data/User/History/b03096/gr1X.cs
Normal file
45
.vscode-server/data/User/History/b03096/gr1X.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using Seasoned.Backend.DTOs;
|
||||
using Mscc.GenerativeAI;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System.IO;
|
||||
|
||||
namespace Seasoned.Backend.Services;
|
||||
|
||||
public class RecipeService : IRecipeService
|
||||
{
|
||||
private readonly string _apiKey;
|
||||
|
||||
public RecipeService(IConfiguration config)
|
||||
{
|
||||
_apiKey = config["GeminiApiKey"] ?? throw new ArgumentNullException("API Key missing");
|
||||
}
|
||||
|
||||
public async Task<RecipeResponseDto> ParseRecipeImageAsync(IFormFile image)
|
||||
{
|
||||
var googleAI = new GoogleAI(_apiKey);
|
||||
var model = googleAI.GenerativeModel("gemini-2.5-flash");
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
await image.CopyToAsync(ms);
|
||||
|
||||
// THE FIX: Convert bytes to a Base64 string for the AddMedia method
|
||||
var base64Image = Convert.ToBase64String(ms.ToArray());
|
||||
|
||||
var prompt = "Extract the recipe from this image. Return Title and Description.";
|
||||
|
||||
var request = new GenerateContentRequest(prompt);
|
||||
|
||||
// This matches the (string, string) signature the compiler is looking for
|
||||
request.AddMedia(base64Image, "image/png");
|
||||
|
||||
var response = await model.GenerateContent(request);
|
||||
|
||||
return new RecipeResponseDto
|
||||
{
|
||||
Title = "Gemini 2.5 Analysis",
|
||||
Description = response.Text ?? "No text returned",
|
||||
Ingredients = new List<string>(),
|
||||
Instructions = new List<string>()
|
||||
};
|
||||
}
|
||||
}
|
||||
38
.vscode-server/data/User/History/b03096/ik8E.cs
Normal file
38
.vscode-server/data/User/History/b03096/ik8E.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using Seasoned.Backend.DTOs;
|
||||
using Mscc.GenerativeAI;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System.IO;
|
||||
|
||||
namespace Seasoned.Backend.Services;
|
||||
|
||||
public class RecipeService : IRecipeService
|
||||
{
|
||||
private readonly string _apiKey;
|
||||
|
||||
public RecipeService(IConfiguration config)
|
||||
{
|
||||
_apiKey = config["GeminiApiKey"] ?? throw new ArgumentNullException("API Key missing");
|
||||
}
|
||||
|
||||
public async Task<RecipeResponseDto> ParseRecipeImageAsync(IFormFile image)
|
||||
{
|
||||
var googleAI = new GoogleAI(_apiKey);
|
||||
var model = googleAI.GenerativeModel("gemini-2.5-flash");
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
await image.CopyToAsync(ms);
|
||||
var imageBytes = ms.ToArray();
|
||||
|
||||
var prompt = "Extract the recipe from this image. Return Title and Description.";
|
||||
|
||||
var response = await model.GenerateContent(prompt, imageBytes, "image/png");
|
||||
|
||||
return new RecipeResponseDto
|
||||
{
|
||||
Title = "Gemini 2.5 Analysis",
|
||||
Description = response.Text ?? "No text returned",
|
||||
Ingredients = new List<string>(),
|
||||
Instructions = new List<string>()
|
||||
};
|
||||
}
|
||||
}
|
||||
51
.vscode-server/data/User/History/b03096/r1gL.cs
Normal file
51
.vscode-server/data/User/History/b03096/r1gL.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using Seasoned.Backend.DTOs;
|
||||
using Mscc.GenerativeAI;
|
||||
|
||||
namespace Seasoned.Backend.Services;
|
||||
|
||||
public class RecipeService : IRecipeService
|
||||
{
|
||||
private readonly string _apiKey;
|
||||
|
||||
public RecipeService(IConfiguration config)
|
||||
{
|
||||
_apiKey = config["GeminiApiKey"] ?? throw new ArgumentNullException("API Key missing");
|
||||
}
|
||||
|
||||
public async Task<RecipeResponseDto> ParseRecipeImageAsync(IFormFile image)
|
||||
{
|
||||
var googleAI = new GoogleAI(_apiKey);
|
||||
var model = googleAI.GenerativeModel("gemini-2.5-flash");
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
await image.CopyToAsync(ms);
|
||||
var base64Image = Convert.ToBase64String(ms.ToArray());
|
||||
|
||||
var prompt = "Extract the recipe from this image. Return Title and Description.";
|
||||
|
||||
GenerateContentRequest request = new()
|
||||
{
|
||||
Contents = new List<Content>
|
||||
{
|
||||
new Content
|
||||
{
|
||||
Parts = new List<Part>
|
||||
{
|
||||
new() { Text = prompt },
|
||||
new() { InlineData = new InlineData { MimeType = "image/png", Data = base64Image } }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var response = await model.GenerateContent((GenerateContentRequest)request);
|
||||
|
||||
return new RecipeResponseDto
|
||||
{
|
||||
Title = "Gemini 2.5 Analysis",
|
||||
Description = response.Text ?? "No text returned",
|
||||
Ingredients = new List<string>(),
|
||||
Instructions = new List<string>()
|
||||
};
|
||||
}
|
||||
}
|
||||
56
.vscode-server/data/User/History/b03096/sqBf.cs
Normal file
56
.vscode-server/data/User/History/b03096/sqBf.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using Seasoned.Backend.DTOs;
|
||||
using Mscc.GenerativeAI;
|
||||
|
||||
namespace Seasoned.Backend.Services;
|
||||
|
||||
public class RecipeService : IRecipeService
|
||||
{
|
||||
private readonly string _apiKey;
|
||||
|
||||
public RecipeService(IConfiguration config)
|
||||
{
|
||||
_apiKey = config["GeminiApiKey"] ?? throw new ArgumentNullException("API Key missing");
|
||||
}
|
||||
|
||||
public async Task<RecipeResponseDto> ParseRecipeImageAsync(IFormFile image)
|
||||
{
|
||||
var googleAI = new GoogleAI(_apiKey);
|
||||
var model = googleAI.GenerativeModel("gemini-2.5-flash");
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
await image.CopyToAsync(ms);
|
||||
var base64Image = Convert.ToBase64String(ms.ToArray());
|
||||
|
||||
var prompt = "Extract the recipe from this image. Return Title and Description.";
|
||||
|
||||
// Use the base Part class with property initializers
|
||||
var parts = new List<Part>
|
||||
{
|
||||
new Part { Text = prompt },
|
||||
new Part { InlineData = new InlineData { MimeType = "image/png", Data = base64Image } }
|
||||
};
|
||||
|
||||
// Use the default constructor and set properties
|
||||
var content = new Content
|
||||
{
|
||||
Role = Role.User,
|
||||
Parts = parts
|
||||
};
|
||||
|
||||
var request = new GenerateContentRequest
|
||||
{
|
||||
Contents = new List<Content> { content }
|
||||
};
|
||||
|
||||
// Casting to solve the ambiguity error we saw earlier
|
||||
var response = await model.GenerateContent((GenerateContentRequest)request);
|
||||
|
||||
return new RecipeResponseDto
|
||||
{
|
||||
Title = "Gemini 2.5 Analysis",
|
||||
Description = response.Text ?? "No text returned",
|
||||
Ingredients = new List<string>(),
|
||||
Instructions = new List<string>()
|
||||
};
|
||||
}
|
||||
}
|
||||
54
.vscode-server/data/User/History/b03096/vh2Y.cs
Normal file
54
.vscode-server/data/User/History/b03096/vh2Y.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
using Seasoned.Backend.DTOs;
|
||||
using Mscc.GenerativeAI;
|
||||
|
||||
namespace Seasoned.Backend.Services;
|
||||
|
||||
public class RecipeService : IRecipeService
|
||||
{
|
||||
private readonly string _apiKey;
|
||||
|
||||
public RecipeService(IConfiguration config)
|
||||
{
|
||||
_apiKey = config["GeminiApiKey"] ?? throw new ArgumentNullException("GeminiApiKey missing in secrets");
|
||||
}
|
||||
|
||||
public async Task<RecipeResponseDto> ParseRecipeImageAsync(IFormFile image)
|
||||
{
|
||||
var googleAI = new GoogleAI(_apiKey);
|
||||
// Using the 2.5 Flash model specifically
|
||||
var model = googleAI.GenerativeModel(Model.Gemini25Flash);
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
await image.CopyToAsync(ms);
|
||||
var base64Image = Convert.ToBase64String(ms.ToArray());
|
||||
|
||||
var prompt = "Extract this recipe. Provide a title and description.";
|
||||
|
||||
// This structure ensures the 2.5 model receives both the text and the image correctly
|
||||
var request = new GenerateContentRequest
|
||||
{
|
||||
Contents = new List<Content>
|
||||
{
|
||||
new Content
|
||||
{
|
||||
Role = Role.User,
|
||||
Parts = new List<Part>
|
||||
{
|
||||
new TextPart { Text = prompt },
|
||||
new InlineDataPart { MimeType = "image/png", Data = base64Image }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var response = await model.GenerateContent(request);
|
||||
|
||||
return new RecipeResponseDto
|
||||
{
|
||||
Title = "Gemini 2.5 Analysis",
|
||||
Description = response.Text ?? "No text returned",
|
||||
Ingredients = new List<string>(),
|
||||
Instructions = new List<string>()
|
||||
};
|
||||
}
|
||||
}
|
||||
51
.vscode-server/data/User/History/b03096/y3ZY.cs
Normal file
51
.vscode-server/data/User/History/b03096/y3ZY.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using Seasoned.Backend.DTOs;
|
||||
using Mscc.GenerativeAI;
|
||||
using System.Linq;
|
||||
|
||||
namespace Seasoned.Backend.Services;
|
||||
|
||||
public class RecipeService : IRecipeService
|
||||
{
|
||||
private readonly string _apiKey;
|
||||
|
||||
public RecipeService(IConfiguration config)
|
||||
{
|
||||
_apiKey = config["GeminiApiKey"] ?? throw new ArgumentNullException("API Key missing");
|
||||
}
|
||||
|
||||
public async Task<RecipeResponseDto> ParseRecipeImageAsync(IFormFile image)
|
||||
{
|
||||
var googleAI = new GoogleAI(_apiKey);
|
||||
var model = googleAI.GenerativeModel("gemini-2.5-flash");
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
await image.CopyToAsync(ms);
|
||||
var base64Image = Convert.ToBase64String(ms.ToArray());
|
||||
|
||||
var prompt = "Extract the recipe from this image. Return Title and Description.";
|
||||
|
||||
// Use the library's internal GenerateContentRequest but manually build the Parts list
|
||||
var request = new GenerateContentRequest();
|
||||
var content = new Content(Role.User);
|
||||
|
||||
// This is the specific syntax to satisfy the IPart list requirement
|
||||
content.Parts = new List<IPart>
|
||||
{
|
||||
new Part { Text = prompt },
|
||||
new Part { InlineData = new InlineData { MimeType = "image/png", Data = base64Image } }
|
||||
}.Cast<IPart>().ToList(); // This 'Cast' is the magic bullet
|
||||
|
||||
request.Contents = new List<Content> { content };
|
||||
|
||||
// Solve the ambiguity by picking the Request overload
|
||||
var response = await model.GenerateContent(request);
|
||||
|
||||
return new RecipeResponseDto
|
||||
{
|
||||
Title = "Gemini 2.5 Analysis",
|
||||
Description = response.Text ?? "No text returned",
|
||||
Ingredients = new List<string>(),
|
||||
Instructions = new List<string>()
|
||||
};
|
||||
}
|
||||
}
|
||||
46
.vscode-server/data/User/History/b03096/yxfK.cs
Normal file
46
.vscode-server/data/User/History/b03096/yxfK.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using Seasoned.Backend.DTOs;
|
||||
using Mscc.GenerativeAI;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System.IO;
|
||||
|
||||
namespace Seasoned.Backend.Services;
|
||||
|
||||
public class RecipeService : IRecipeService
|
||||
{
|
||||
private readonly string _apiKey;
|
||||
|
||||
public RecipeService(IConfiguration config)
|
||||
{
|
||||
_apiKey = config["GeminiApiKey"] ?? throw new ArgumentNullException("API Key missing");
|
||||
}
|
||||
|
||||
public async Task<RecipeResponseDto> ParseRecipeImageAsync(IFormFile image)
|
||||
{
|
||||
var googleAI = new GoogleAI(_apiKey);
|
||||
var model = googleAI.GenerativeModel(Model.Gemini25Flash);
|
||||
|
||||
using var ms = new MemoryStream();
|
||||
await image.CopyToAsync(ms);
|
||||
var imageBytes = ms.ToArray();
|
||||
|
||||
var prompt = "Extract the recipe from this image. Return Title and Description.";
|
||||
|
||||
// 1. Create the request with just the text prompt first
|
||||
var request = new GenerateContentRequest(prompt);
|
||||
|
||||
// 2. Use the built-in AddMedia helper.
|
||||
// This automatically handles the IPart/InlineData wrapping for you!
|
||||
request.AddMedia(imageBytes, "image/png");
|
||||
|
||||
// 3. Send the request
|
||||
var response = await model.GenerateContent(request);
|
||||
|
||||
return new RecipeResponseDto
|
||||
{
|
||||
Title = "Gemini 2.5 Analysis",
|
||||
Description = response.Text ?? "No text returned",
|
||||
Ingredients = new List<string>(),
|
||||
Instructions = new List<string>()
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user