Add file analysis and answer feedback
This commit is contained in:
+65
-6
@@ -1,6 +1,7 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:file_selector/file_selector.dart';
|
||||
|
||||
import '../../../../core/network/api_repository.dart';
|
||||
import 'chat_state.dart';
|
||||
@@ -162,8 +163,8 @@ class ChatCubit extends Cubit<ChatState> {
|
||||
await _api.saveConversation(item);
|
||||
}
|
||||
|
||||
Future<void> send(String text) async {
|
||||
await _sendWithHistory(text, state.messages);
|
||||
Future<void> send(String text, {List<XFile> attachments = const []}) async {
|
||||
await _sendWithHistory(text, state.messages, attachments: attachments);
|
||||
}
|
||||
|
||||
Future<void> regenerateLastAnswer() async {
|
||||
@@ -185,6 +186,7 @@ class ChatCubit extends Cubit<ChatState> {
|
||||
history,
|
||||
appendUserMessage: false,
|
||||
previousAnswers: versions,
|
||||
previousFeedback: previousAnswer.feedbackVersions,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -206,6 +208,7 @@ class ChatCubit extends Cubit<ChatState> {
|
||||
versions[versionIndex],
|
||||
fromUser: false,
|
||||
answerVersions: versions,
|
||||
feedbackVersions: message.feedbackVersions,
|
||||
selectedVersion: versionIndex,
|
||||
);
|
||||
try {
|
||||
@@ -216,6 +219,43 @@ class ChatCubit extends Cubit<ChatState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> rateAnswer(int messageIndex, int rating) async {
|
||||
if (state.isSending || (rating != -1 && rating != 1)) return;
|
||||
final conversationId = state.activeConversationId;
|
||||
if (conversationId == null ||
|
||||
messageIndex < 0 ||
|
||||
messageIndex >= state.messages.length) {
|
||||
return;
|
||||
}
|
||||
final messages = List<ChatMessage>.from(state.messages);
|
||||
final message = messages[messageIndex];
|
||||
if (message.fromUser || message.answerVersions.isEmpty) return;
|
||||
try {
|
||||
await _api.rateAnswer(
|
||||
conversationId,
|
||||
messageIndex,
|
||||
message.selectedVersion,
|
||||
rating,
|
||||
);
|
||||
final feedback = List<int?>.generate(
|
||||
message.answerVersions.length,
|
||||
(index) => index < message.feedbackVersions.length
|
||||
? message.feedbackVersions[index]
|
||||
: null,
|
||||
)..[message.selectedVersion] = rating;
|
||||
messages[messageIndex] = ChatMessage(
|
||||
message.text,
|
||||
fromUser: false,
|
||||
answerVersions: message.answerVersions,
|
||||
feedbackVersions: feedback,
|
||||
selectedVersion: message.selectedVersion,
|
||||
);
|
||||
emit(state.copyWith(messages: messages, clearError: true));
|
||||
} catch (error) {
|
||||
emit(state.copyWith(error: 'تعذر حفظ تقييم الإجابة: $error'));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> editLastQuestion(String text) async {
|
||||
if (state.isSending || text.trim().isEmpty) return;
|
||||
final messages = state.messages;
|
||||
@@ -235,12 +275,21 @@ class ChatCubit extends Cubit<ChatState> {
|
||||
List<ChatMessage> history, {
|
||||
bool appendUserMessage = true,
|
||||
List<String> previousAnswers = const [],
|
||||
List<int?> previousFeedback = const [],
|
||||
List<XFile> attachments = const [],
|
||||
}) async {
|
||||
final prompt = text.trim();
|
||||
final prompt =
|
||||
text.trim().isEmpty && attachments.isNotEmpty
|
||||
? 'حلّل الملفات المرفقة واشرح وظيفتها.'
|
||||
: text.trim();
|
||||
if (prompt.isEmpty || state.isSending || state.isLoadingHistory) return;
|
||||
final displayPrompt =
|
||||
attachments.isEmpty
|
||||
? prompt
|
||||
: '$prompt\n\n[ملفات مرفقة: ${attachments.map((file) => file.name).join('، ')}]';
|
||||
final messages =
|
||||
appendUserMessage
|
||||
? [...history, ChatMessage(prompt, fromUser: true)]
|
||||
? [...history, ChatMessage(displayPrompt, fromUser: true)]
|
||||
: List<ChatMessage>.from(history);
|
||||
final originalMessages = state.messages;
|
||||
_messagesBeforeRequest = originalMessages;
|
||||
@@ -267,9 +316,15 @@ class ChatCubit extends Cubit<ChatState> {
|
||||
),
|
||||
);
|
||||
_startElapsedTimer(generation);
|
||||
if (state.isWorkspaceMode || state.isWebSearchMode) {
|
||||
if (attachments.isNotEmpty || state.isWorkspaceMode || state.isWebSearchMode) {
|
||||
answer =
|
||||
state.isWorkspaceMode
|
||||
attachments.isNotEmpty
|
||||
? await _api.analyzeFiles(
|
||||
attachments,
|
||||
prompt.isEmpty ? 'حلّل الملفات المرفقة واشرح وظيفتها.' : prompt,
|
||||
model: state.selectedModel,
|
||||
)
|
||||
: state.isWorkspaceMode
|
||||
? await _api.askWorkspaceAgent(prompt, model: state.selectedModel)
|
||||
: await _api.searchWeb(prompt, model: state.selectedModel);
|
||||
if (isClosed || generation != _requestGeneration) return;
|
||||
@@ -283,6 +338,7 @@ class ChatCubit extends Cubit<ChatState> {
|
||||
answer,
|
||||
fromUser: false,
|
||||
answerVersions: answerVersions,
|
||||
feedbackVersions: [...previousFeedback, null],
|
||||
selectedVersion: answerVersions.length - 1,
|
||||
),
|
||||
];
|
||||
@@ -315,6 +371,7 @@ class ChatCubit extends Cubit<ChatState> {
|
||||
answer,
|
||||
fromUser: false,
|
||||
answerVersions: answerVersions,
|
||||
feedbackVersions: [...previousFeedback, null],
|
||||
selectedVersion: answerVersions.length - 1,
|
||||
),
|
||||
],
|
||||
@@ -330,6 +387,7 @@ class ChatCubit extends Cubit<ChatState> {
|
||||
answer,
|
||||
fromUser: false,
|
||||
answerVersions: answerVersions,
|
||||
feedbackVersions: [...previousFeedback, null],
|
||||
selectedVersion: answerVersions.length - 1,
|
||||
),
|
||||
];
|
||||
@@ -358,6 +416,7 @@ class ChatCubit extends Cubit<ChatState> {
|
||||
answer,
|
||||
fromUser: false,
|
||||
answerVersions: [...previousAnswers, answer],
|
||||
feedbackVersions: [...previousFeedback, null],
|
||||
selectedVersion: previousAnswers.length,
|
||||
),
|
||||
];
|
||||
|
||||
@@ -7,18 +7,21 @@ class ChatMessage {
|
||||
this.text, {
|
||||
required this.fromUser,
|
||||
this.answerVersions = const [],
|
||||
this.feedbackVersions = const [],
|
||||
this.selectedVersion = 0,
|
||||
});
|
||||
|
||||
final String text;
|
||||
final bool fromUser;
|
||||
final List<String> answerVersions;
|
||||
final List<int?> feedbackVersions;
|
||||
final int selectedVersion;
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'text': text,
|
||||
'fromUser': fromUser,
|
||||
'answerVersions': answerVersions,
|
||||
'feedbackVersions': feedbackVersions,
|
||||
'selectedVersion': selectedVersion,
|
||||
};
|
||||
|
||||
@@ -27,6 +30,10 @@ class ChatMessage {
|
||||
fromUser: json['fromUser'] as bool,
|
||||
answerVersions:
|
||||
(json['answerVersions'] as List<dynamic>? ?? const []).cast<String>(),
|
||||
feedbackVersions:
|
||||
(json['feedbackVersions'] as List<dynamic>? ?? const [])
|
||||
.map((value) => value as int?)
|
||||
.toList(),
|
||||
selectedVersion: json['selectedVersion'] as int? ?? 0,
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user