using System.Net; using System.Text.Json; using Microsoft.Azure.Functions.Worker; using Microsoft.Azure.Functions.Worker.Http; using Microsoft.Extensions.Logging; using Google.GenAI; using System.Text.Json.Serialization; namespace CognitiveClarity.api { public class AnalysisRequest { [JsonPropertyName("turnContext")] public string TurnContext { get; set; } = string.Empty; [JsonPropertyName("scenarioTitle")] public string ScenarioTitle { get; set; } = string.Empty; [JsonPropertyName("scenarioDescription")] public string ScenarioDescription { get; set; } = string.Empty; [JsonPropertyName("cbtFocus")] public List CBTFocus { get; set; } = new(); } public class AnalysisFunction { private readonly ILogger _logger; public AnalysisFunction(ILoggerFactory loggerFactory) { _logger = loggerFactory.CreateLogger(); } [Function("ClinicalAnalysis")] public async Task Run( [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "analysis")] HttpRequestData req) { _logger.LogInformation("C# HTTP trigger function processed a clinical analysis request."); var requestBody = await new StreamReader(req.Body).ReadToEndAsync(); var data = JsonSerializer.Deserialize(requestBody); if (data == null || string.IsNullOrWhiteSpace(data.TurnContext)) { var badResponse = req.CreateResponse(HttpStatusCode.BadRequest); await badResponse.WriteStringAsync("Please provide turnContext in the request body"); return badResponse; } var apiKey = Environment.GetEnvironmentVariable("GEMINI_API_KEY"); if (string.IsNullOrEmpty(apiKey)) { _logger.LogError("GEMINI_API_KEY is missing from environment variables."); return req.CreateResponse(HttpStatusCode.InternalServerError); } // Initialize the Gemini Client var ai = new GeminiClient(apiKey: apiKey); var systemAnalysisPrompt = @" You are a master clinical psychologist specializing in Cognitive Behavioral Therapy (CBT). You are observing a roleplay session between a user and an AI character. Analyze the user's latest response for: 1. Cognitive distortions present (if any). 2. CBT techniques successfully applied by the user (if any). 3. A brief, encouraging clinical insight or redirection (max 2 sentences). Be precise, clinical, and constructive. "; var analysisSystemInstruction = $@"{systemAnalysisPrompt} SCENARIO CONTEXT: Title: {data.ScenarioTitle} Description: {data.ScenarioDescription} CBT Focus Areas: {string.Join(", ", data.CBTFocus)}"; var schema = new Schema { Type = TypeEnum.Object, Properties = new Dictionary { { "distortionsIdentified", new Schema { Type = TypeEnum.Array, Items = new Schema { Type = TypeEnum.String } } }, { "techniquesUsed", new Schema { Type = TypeEnum.Array, Items = new Schema { Type = TypeEnum.String } } }, { "clinicalInsight", new Schema { Type = TypeEnum.String } }, { "feedbackType", new Schema { Type = TypeEnum.String, Enum = new List { "Constructive", "Positive", "Neutral" } } } }, Required = new List { "distortionsIdentified", "techniquesUsed", "clinicalInsight", "feedbackType" } }; try { var response = await ai.Models.GenerateContentAsync( model: "gemini-3.0-flash", contents: data.TurnContext, new GenerateContentConfig { SystemInstruction = new Content { Parts = new List { new Part { Text = analysisSystemInstruction } } }, ResponseMimeType = "application/json", ResponseSchema = schema }); var successResponse = req.CreateResponse(HttpStatusCode.OK); successResponse.Headers.Add("Content-Type", "application/json"); await successResponse.WriteStringAsync(response.Text!); return successResponse; } catch (Exception ex) { _logger.LogError(ex, "Failed to generate analysis via Gemini API."); var errorResponse = req.CreateResponse(HttpStatusCode.InternalServerError); await errorResponse.WriteStringAsync("Error communicating with Gemini API."); return errorResponse; } } } }