From 856ce034e699d93dfa0efe411ee789a106bae2f6 Mon Sep 17 00:00:00 2001 From: siddu015 <116783967+siddu015@users.noreply.github.com> Date: Sat, 22 Feb 2025 22:44:06 +0530 Subject: [PATCH 1/3] Feat: Added DebugApi --- lib/services/ollama_service.dart | 31 +++++++++++++++++++++++++++++++ lib/widgets/chatbot_widget.dart | 20 ++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/lib/services/ollama_service.dart b/lib/services/ollama_service.dart index f6ae682f..8179b211 100644 --- a/lib/services/ollama_service.dart +++ b/lib/services/ollama_service.dart @@ -39,4 +39,35 @@ class OllamaService { '''; return generateResponse(prompt); } + + Future debugApi({required dynamic requestModel, required dynamic responseModel}) async { + if (requestModel == null || responseModel == null) { + return "There are no recent API Requests to debug."; + } + + final requestJson = jsonEncode(requestModel.toJson()); + final responseJson = jsonEncode(responseModel.toJson()); + final statusCode = responseModel.statusCode; + + final prompt = ''' + Provide detailed debugging steps for this failed API request: + + **Status Code:** $statusCode + **Request Details:** + $requestJson + + **Response Details:** + $responseJson + + Provide a step-by-step debugging guide including: + 1. Common causes for this status code + 2. Specific issues in the request + 3. Potential fixes + 4. Recommended next steps + + Format the response with clear headings and bullet points. + '''; + + return generateResponse(prompt); + } } diff --git a/lib/widgets/chatbot_widget.dart b/lib/widgets/chatbot_widget.dart index 56246980..44f8278c 100644 --- a/lib/widgets/chatbot_widget.dart +++ b/lib/widgets/chatbot_widget.dart @@ -33,6 +33,11 @@ class _ChatbotWidgetState extends ConsumerState { requestModel: requestModel, responseModel: responseModel, ); + } else if (message == "Debug API") { + response = await ollamaService.debugApi( + requestModel: requestModel, + responseModel: responseModel, + ); } else { response = await ollamaService.generateResponse(message); } @@ -51,6 +56,10 @@ class _ChatbotWidgetState extends ConsumerState { @override Widget build(BuildContext context) { + final requestModel = ref.watch(selectedRequestModelProvider); + final statusCode = requestModel?.httpResponseModel?.statusCode; + final showDebugButton = statusCode != null && statusCode >= 400; + return Container( height: 400, padding: const EdgeInsets.all(16), @@ -70,6 +79,17 @@ class _ChatbotWidgetState extends ConsumerState { icon: const Icon(Icons.info_outline), label: const Text("Explain API"), ), + if (showDebugButton) ...[ + const SizedBox(width: 8), + ElevatedButton.icon( + onPressed: () => _sendMessage("Debug API"), + icon: const Icon(Icons.bug_report), + label: const Text("Debug"), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.redAccent, + ), + ), + ], const Spacer(), ], ), From 1e60780a3d04e87557947864172e1d542c0455ed Mon Sep 17 00:00:00 2001 From: siddu015 <116783967+siddu015@users.noreply.github.com> Date: Sun, 23 Feb 2025 01:41:05 +0530 Subject: [PATCH 2/3] Feat: Added Generate Test Cases and moved short prompting examples to another function --- lib/services/ollama_service.dart | 154 ++++++++++++++++++++++++++++--- lib/widgets/chatbot_widget.dart | 16 ++++ 2 files changed, 157 insertions(+), 13 deletions(-) diff --git a/lib/services/ollama_service.dart b/lib/services/ollama_service.dart index 8179b211..9feae827 100644 --- a/lib/services/ollama_service.dart +++ b/lib/services/ollama_service.dart @@ -20,23 +20,52 @@ class OllamaService { // Explain latest API request & response Future explainLatestApi({required dynamic requestModel, required dynamic responseModel}) async { if (requestModel == null || responseModel == null) { - return "There are no recent API Requests."; + return "No recent API requests found"; } - final requestJson = jsonEncode(requestModel.toJson()); - final responseJson = jsonEncode(responseModel.toJson()); + // Extract request details + final method = requestModel.httpRequestModel?.method + .toString() + .split('.') + .last + .toUpperCase() + ?? "GET"; + final endpoint = requestModel.httpRequestModel?.url ?? "Unknown endpoint"; + final headers = requestModel.httpRequestModel?.enabledHeadersMap ?? {}; + final parameters = requestModel.httpRequestModel?.enabledParamsMap ?? {}; + final body = requestModel.httpRequestModel?.body; + + // Process response + final rawResponse = responseModel.body; + final responseBody = rawResponse is String; + final statusCode = responseModel.statusCode ?? 0; final prompt = ''' - Explain the API request and response in a simple way: - - **Request Details:** - $requestJson - - **Response Details:** - $responseJson - - Please provide a brief and clear explanation with key insights. - '''; +Analyze this API interaction following these examples: + +Current API Request: +- Endpoint: $endpoint +- Method: $method +- Headers: ${headers.isNotEmpty ? jsonEncode(headers) : "None"} +- Parameters: ${parameters.isNotEmpty ? jsonEncode(parameters) : "None"} +- Body: ${body ?? "None"} + +Current Response: +- Status Code: $statusCode +- Response Body: ${jsonEncode(responseBody)} + +Required Analysis Format: +1. Start with overall status assessment +2. List validation/security issues +3. Highlight request/response mismatches +4. Suggest concrete improvements +5. Use plain text formatting with clear section headers + +Response Structure: +API Request: [request details] +Response: [response details] +Analysis: [structured analysis]'''; + return generateResponse(prompt); } @@ -70,4 +99,103 @@ class OllamaService { return generateResponse(prompt); } + + Future generateTestCases({required dynamic requestModel, required dynamic responseModel}) async { + + final method = requestModel.httpRequestModel?.method + .toString() + .split('.') + .last + .toUpperCase() + ?? "GET"; + final endpoint = requestModel.httpRequestModel?.url ?? "Unknown endpoint"; + final headers = requestModel.httpRequestModel?.enabledHeadersMap ?? {}; + final parameters = requestModel.httpRequestModel?.enabledParamsMap ?? {}; + final body = requestModel.httpRequestModel?.body; + final exampleParams = await generateExampleParams( + requestModel: requestModel, + responseModel: responseModel, + ); + final prompt = ''' +Generate test cases for the following API: + +**API Request:** +- **Endpoint:** `$endpoint` +- **Method:** `$method` +- **Headers:** ${headers.isNotEmpty ? jsonEncode(headers) : "None"} +- **Parameters:** ${parameters.isNotEmpty ? jsonEncode(parameters) : "None"} + +**Test Case Requirements:** +1. Normal case (valid input, expected success) +2. Edge case (unexpected or boundary values) +3. Missing required parameters +4. Invalid authentication (if applicable) +5. Error handling for different status codes + +**Example Test Case Format:** +@Test +void testValidRequest() { + final response = sendRequest("$endpoint", method: "$method", params: $exampleParams); + assert(response.status == 200); +} +\`\`\` + +Generate test cases covering all scenarios. +'''; + + return generateResponse(prompt); + } + + /// Generate example parameter values based on parameter names + Future> generateExampleParams({required dynamic requestModel, required dynamic responseModel,}) async { + final ollamaService = OllamaService(); + + final method = requestModel.httpRequestModel?.method + .toString() + .split('.') + .last + .toUpperCase() + ?? "GET"; + final endpoint = requestModel.httpRequestModel?.url ?? "Unknown endpoint"; + final headers = requestModel.httpRequestModel?.enabledHeadersMap ?? {}; + final parameters = requestModel.httpRequestModel?.enabledParamsMap ?? {}; + final body = requestModel.httpRequestModel?.body; + + + final dynamic rawResponse = responseModel?.body; + final Map? apiResponse = + (rawResponse is String) ? jsonDecode(rawResponse) : rawResponse is Map ? rawResponse : null; + + // Construct LLM prompt to analyze and extract meaningful test cases + final String prompt = ''' +Analyze the following API request and generate structured example parameters. + +**API Request:** +- **Endpoint:** `$endpoint` +- **Method:** `$method` +- **Headers:** ${headers.isNotEmpty ? jsonEncode(headers) : "None"} +- **Parameters:** ${parameters.isNotEmpty ? jsonEncode(parameters) : "None"} +- **Body:** ${body ?? "None"} + +**Response:** +- **Status Code:** ${responseModel?.statusCode ?? "Unknown"} +- **Response Body:** ${apiResponse != null ? jsonEncode(apiResponse) : rawResponse} + +### **Required Output Format** +1. **Standard Example Values**: Assign the most appropriate example values for each parameter. +2. **Edge Cases**: Provide at least 2 edge cases per parameter. +3. **Invalid Cases**: Generate invalid inputs for error handling. +4. **Output must be in valid JSON format.** +'''; + + // Force LLM to return structured JSON output + final String response = await ollamaService.generateResponse(prompt); + + try { + return jsonDecode(response) as Map; + } catch (e) { + return {"error": "Failed to parse response from LLM."}; + } + + } } diff --git a/lib/widgets/chatbot_widget.dart b/lib/widgets/chatbot_widget.dart index 44f8278c..687f7e5e 100644 --- a/lib/widgets/chatbot_widget.dart +++ b/lib/widgets/chatbot_widget.dart @@ -38,6 +38,11 @@ class _ChatbotWidgetState extends ConsumerState { requestModel: requestModel, responseModel: responseModel, ); + } else if (message == "Generate Test Case") { + response = await ollamaService.generateTestCases( + requestModel: requestModel, + responseModel: responseModel + ); } else { response = await ollamaService.generateResponse(message); } @@ -91,6 +96,17 @@ class _ChatbotWidgetState extends ConsumerState { ), ], const Spacer(), + const SizedBox(width: 8), + ElevatedButton.icon( + onPressed: () => _sendMessage("Generate Test Case"), + icon: const Icon(Icons.developer_mode), + label: const Text("Test Case"), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.blueAccent, + ), + ), + + const Spacer(), ], ), Expanded( From 72ab1740ed25e6c2ba9d39af77f2c8753da61a2b Mon Sep 17 00:00:00 2001 From: DhumalePrasad04 Date: Sun, 23 Feb 2025 10:40:46 +0530 Subject: [PATCH 3/3] generateTestCases prompting improved for structured responses --- lib/services/ollama_service.dart | 39 +++++++++++--------------------- lib/widgets/chatbot_widget.dart | 14 +++++------- 2 files changed, 19 insertions(+), 34 deletions(-) diff --git a/lib/services/ollama_service.dart b/lib/services/ollama_service.dart index 9feae827..0e675763 100644 --- a/lib/services/ollama_service.dart +++ b/lib/services/ollama_service.dart @@ -10,7 +10,7 @@ class OllamaService { Future generateResponse(String prompt) async { final response = await _client.generateCompletion( request: GenerateCompletionRequest( - model: 'llama3.2:3b', + model: 'llama3.2:1b', prompt: prompt ), ); @@ -112,35 +112,25 @@ Analysis: [structured analysis]'''; final headers = requestModel.httpRequestModel?.enabledHeadersMap ?? {}; final parameters = requestModel.httpRequestModel?.enabledParamsMap ?? {}; final body = requestModel.httpRequestModel?.body; + final responsebody=responseModel.body; final exampleParams = await generateExampleParams( requestModel: requestModel, responseModel: responseModel, ); final prompt = ''' -Generate test cases for the following API: - **API Request:** - **Endpoint:** `$endpoint` - **Method:** `$method` - **Headers:** ${headers.isNotEmpty ? jsonEncode(headers) : "None"} - **Parameters:** ${parameters.isNotEmpty ? jsonEncode(parameters) : "None"} +-**body:** ${body ?? "None"} -**Test Case Requirements:** -1. Normal case (valid input, expected success) -2. Edge case (unexpected or boundary values) -3. Missing required parameters -4. Invalid authentication (if applicable) -5. Error handling for different status codes +here is an example test case for the given:$exampleParams -**Example Test Case Format:** -@Test -void testValidRequest() { - final response = sendRequest("$endpoint", method: "$method", params: $exampleParams); - assert(response.status == 200); -} -\`\`\` - -Generate test cases covering all scenarios. +**Instructions:** +- Generate example parameter values for the request. +-Generate the url of as i provided in the api reuest +-generate same to same type of test case url for test purpose '''; return generateResponse(prompt); @@ -177,15 +167,12 @@ Analyze the following API request and generate structured example parameters. - **Parameters:** ${parameters.isNotEmpty ? jsonEncode(parameters) : "None"} - **Body:** ${body ?? "None"} -**Response:** -- **Status Code:** ${responseModel?.statusCode ?? "Unknown"} -- **Response Body:** ${apiResponse != null ? jsonEncode(apiResponse) : rawResponse} -### **Required Output Format** -1. **Standard Example Values**: Assign the most appropriate example values for each parameter. -2. **Edge Cases**: Provide at least 2 edge cases per parameter. -3. **Invalid Cases**: Generate invalid inputs for error handling. -4. **Output must be in valid JSON format.** +**Instructions:** +- Generate example parameter values for the request. +-Generate the url of as i provided in the api reuest +generate same to same type of test case url for test purpose + '''; // Force LLM to return structured JSON output diff --git a/lib/widgets/chatbot_widget.dart b/lib/widgets/chatbot_widget.dart index 687f7e5e..bc685ccc 100644 --- a/lib/widgets/chatbot_widget.dart +++ b/lib/widgets/chatbot_widget.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:apidash/providers/providers.dart'; +import 'package:flutter_markdown/flutter_markdown.dart'; + class ChatbotWidget extends ConsumerStatefulWidget { const ChatbotWidget({Key? key}) : super(key: key); @@ -90,20 +92,13 @@ class _ChatbotWidgetState extends ConsumerState { onPressed: () => _sendMessage("Debug API"), icon: const Icon(Icons.bug_report), label: const Text("Debug"), - style: ElevatedButton.styleFrom( - backgroundColor: Colors.redAccent, - ), ), ], - const Spacer(), const SizedBox(width: 8), ElevatedButton.icon( onPressed: () => _sendMessage("Generate Test Case"), icon: const Icon(Icons.developer_mode), label: const Text("Test Case"), - style: ElevatedButton.styleFrom( - backgroundColor: Colors.blueAccent, - ), ), const Spacer(), @@ -171,7 +166,10 @@ class ChatBubble extends StatelessWidget { : Theme.of(context).colorScheme.secondaryContainer, borderRadius: BorderRadius.circular(8), ), - child: Text(message), + child: MarkdownBody( + data: message, + selectable: true, // Allows copying text + ), ), ); }