diff --git a/PatchPanda.Web/Services/OllamaService.cs b/PatchPanda.Web/Services/OllamaService.cs index 0b508d1..ca5af3f 100644 --- a/PatchPanda.Web/Services/OllamaService.cs +++ b/PatchPanda.Web/Services/OllamaService.cs @@ -58,7 +58,11 @@ IHttpClientFactory httpClientFactory public bool IsInitialized() => _isInitialized; - private async Task SendPrompt(string prompt, string? enforceFormat = null) + private async Task SendPrompt( + string prompt, + string? enforceFormat = null, + string? systemPrompt = null + ) where T : class, IAiResult { if (!_isInitialized) @@ -73,6 +77,7 @@ IHttpClientFactory httpClientFactory var request = new { model = _model, + system = systemPrompt, prompt = prompt + (enforceFormatString ?? string.Empty), stream = false, options = new { num_ctx = _contextSize }, @@ -112,7 +117,8 @@ IHttpClientFactory httpClientFactory Func extractChunkSummary, Func, string> buildFinalPrompt, Func, T> buildFallback, - string? jsonTemplate = null + string? jsonTemplate = null, + string? systemPrompt = null ) where T : class, IAiResult { @@ -127,7 +133,7 @@ IHttpClientFactory httpClientFactory maxCharsPerChunk = 4096; // Fallback if (text.Length <= maxCharsPerChunk) - return await SendPrompt(buildPrompt(text), jsonTemplate); + return await SendPrompt(buildPrompt(text), jsonTemplate, systemPrompt); _logger.LogInformation( "Text is too large ({Length} chars), splitting into chunks...", @@ -145,7 +151,7 @@ IHttpClientFactory httpClientFactory for (var i = 0; i < chunks.Count; i++) { _logger.LogInformation("Processing chunk {Current}/{Total}...", i + 1, chunks.Count); - var result = await SendPrompt(buildPrompt(chunks[i]), jsonTemplate); + var result = await SendPrompt(buildPrompt(chunks[i]), jsonTemplate, systemPrompt); if (result == null) continue; @@ -159,7 +165,7 @@ IHttpClientFactory httpClientFactory _logger.LogInformation("Requesting final summary of all chunk summaries from the model..."); var finalPrompt = buildFinalPrompt(perChunkSummaries); - var finalResult = await SendPrompt(finalPrompt, jsonTemplate); + var finalResult = await SendPrompt(finalPrompt, jsonTemplate, systemPrompt); return finalResult ?? buildFallback(perChunkResults); } @@ -190,6 +196,8 @@ IHttpClientFactory httpClientFactory public async Task AnalyzeDiff(string diff) { + var today = DateTime.UtcNow.ToString("yyyy-MM-dd"); + return await SendPromptWithChunking( diff, whole => @@ -207,7 +215,8 @@ IHttpClientFactory httpClientFactory Analysis = string.Join("\n\n", results.Select(r => r.Analysis)), IsSuspectedMalicious = results.Any(r => r.IsSuspectedMalicious), }, - "{\"analysis\": string (short summary of findings), \"isSuspectedMalicious\": bool}" + "{\"analysis\": string (short summary of findings), \"isSuspectedMalicious\": bool}", + $"You are a security expert reviewing git diffs for supply-chain and malware risks. Today's date is {today}. Treat date-based version numbers and release tags around this date as normal unless there is other evidence of malicious intent." ); }