From f19993bb30413a159627e1cefa36f59a3e23d6ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Poizat?= Date: Mon, 8 Dec 2025 14:59:42 +0100 Subject: [PATCH] Use json_serializable and const to improve AI data model --- .../scribe/ai/data/model/ai_api_request.dart | 4 +- .../scribe/ai/data/model/ai_api_response.dart | 59 +++++++++++-------- .../lib/scribe/ai/data/model/ai_message.dart | 14 +++-- scribe/lib/scribe/ai/data/network/ai_api.dart | 7 +-- .../scribe/ai/domain/model/ai_response.dart | 2 +- 5 files changed, 49 insertions(+), 37 deletions(-) diff --git a/scribe/lib/scribe/ai/data/model/ai_api_request.dart b/scribe/lib/scribe/ai/data/model/ai_api_request.dart index 84c171bb1..8dab00d17 100644 --- a/scribe/lib/scribe/ai/data/model/ai_api_request.dart +++ b/scribe/lib/scribe/ai/data/model/ai_api_request.dart @@ -1,6 +1,8 @@ import 'ai_message.dart'; class AIAPIRequest { + static const String _defaultModel = 'gpt-oss-120b'; + final List messages; const AIAPIRequest({ @@ -9,7 +11,7 @@ class AIAPIRequest { Map toJson() { return { - 'model': 'gpt-oss-120b', + 'model': _defaultModel, 'messages': messages.map((m) => m.toJson()).toList(), }; } diff --git a/scribe/lib/scribe/ai/data/model/ai_api_response.dart b/scribe/lib/scribe/ai/data/model/ai_api_response.dart index c479a60ad..b949642d5 100644 --- a/scribe/lib/scribe/ai/data/model/ai_api_response.dart +++ b/scribe/lib/scribe/ai/data/model/ai_api_response.dart @@ -1,31 +1,44 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'ai_api_response.g.dart'; + +@JsonSerializable() class AIApiResponse { - final String content; + final List choices; const AIApiResponse({ + required this.choices + }); + + factory AIApiResponse.fromJson(Map json) => _$AIApiResponseFromJson(json); + + Map toJson() => _$AIApiResponseToJson(this); + + String? get content => choices.isNotEmpty ? choices[0].message.content : null; +} + +@JsonSerializable() +class Choice { + final Message message; + + const Choice({ + required this.message + }); + + factory Choice.fromJson(Map json) => _$ChoiceFromJson(json); + + Map toJson() => _$ChoiceToJson(this); +} + +@JsonSerializable() +class Message { + final String content; + + const Message({ required this.content }); - static AIApiResponse? parse(Map json) { - final choices = json['choices'] as List?; - if (choices == null || choices.isEmpty) { - return null; - } + factory Message.fromJson(Map json) => _$MessageFromJson(json); - final firstChoice = choices[0] as Map?; - if (firstChoice == null) { - return null; - } - - final message = firstChoice['message'] as Map?; - if (message == null) { - return null; - } - - final content = message['content'] as String?; - if (content == null || content.isEmpty) { - return null; - } - - return AIApiResponse(content: content); - } + Map toJson() => _$MessageToJson(this); } diff --git a/scribe/lib/scribe/ai/data/model/ai_message.dart b/scribe/lib/scribe/ai/data/model/ai_message.dart index 01684fd4c..9f318800c 100644 --- a/scribe/lib/scribe/ai/data/model/ai_message.dart +++ b/scribe/lib/scribe/ai/data/model/ai_message.dart @@ -1,3 +1,8 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'ai_message.g.dart'; + +@JsonSerializable() class AIMessage { final String role; final String content; @@ -7,10 +12,7 @@ class AIMessage { required this.content, }); - Map toJson() { - return { - 'role': role, - 'content': content, - }; - } + factory AIMessage.fromJson(Map json) => _$AIMessageFromJson(json); + + Map toJson() => _$AIMessageToJson(this); } diff --git a/scribe/lib/scribe/ai/data/network/ai_api.dart b/scribe/lib/scribe/ai/data/network/ai_api.dart index a210ac914..c9f7bd99c 100644 --- a/scribe/lib/scribe/ai/data/network/ai_api.dart +++ b/scribe/lib/scribe/ai/data/network/ai_api.dart @@ -28,12 +28,7 @@ class AIApi { ); if (response.statusCode == 200) { - final parsedResponse = AIApiResponse.parse(response.data); - if (parsedResponse != null) { - return parsedResponse; - } else { - throw Exception('Empty response from AI service'); - } + return AIApiResponse.fromJson(response.data); } else { throw Exception('AI API returned status code: ${response.statusCode}'); } diff --git a/scribe/lib/scribe/ai/domain/model/ai_response.dart b/scribe/lib/scribe/ai/domain/model/ai_response.dart index 2f73960f2..3d851da25 100644 --- a/scribe/lib/scribe/ai/domain/model/ai_response.dart +++ b/scribe/lib/scribe/ai/domain/model/ai_response.dart @@ -1,5 +1,5 @@ class AIResponse { - final String result; + final String? result; const AIResponse({required this.result});