122 lines
3.2 KiB
Dart
122 lines
3.2 KiB
Dart
import 'dart:convert';
|
|
import 'package:didvan/services/auth/token_storage.dart';
|
|
import 'package:didvan/services/network/request.dart';
|
|
import 'package:didvan/services/network/request_helper.dart';
|
|
import 'package:http/http.dart' as http;
|
|
|
|
class AiRagService {
|
|
static const String _ragUrl = '${RequestHelper.newApiBaseUrl}/rag-query';
|
|
static const String _didvanBaseUrl = 'https://api.didvan.app';
|
|
|
|
static String _getFullAudioUrl(String? url) {
|
|
if (url == null || url.isEmpty) return '';
|
|
|
|
if (url.startsWith('http://') || url.startsWith('https://')) {
|
|
return url;
|
|
}
|
|
|
|
if (url.startsWith('/')) {
|
|
return '$_didvanBaseUrl$url';
|
|
}
|
|
|
|
return '$_didvanBaseUrl/$url';
|
|
}
|
|
|
|
static Future<AiRagResponse> sendMessage(
|
|
String message, {
|
|
int? topK,
|
|
bool? includeSources,
|
|
}) async {
|
|
try {
|
|
final token = TokenStorage.accessToken ?? RequestService.token ?? '';
|
|
|
|
final Map<String, String> headers = {
|
|
'Content-Type': 'application/json',
|
|
'Accept': '*/*',
|
|
};
|
|
|
|
if (token.isNotEmpty) {
|
|
headers['Authorization'] = 'Bearer $token';
|
|
}
|
|
|
|
final Map<String, dynamic> body = {
|
|
'question': message,
|
|
};
|
|
|
|
if (topK != null) {
|
|
body['topK'] = topK;
|
|
}
|
|
if (includeSources != null) {
|
|
body['includeSources'] = includeSources;
|
|
}
|
|
|
|
final response = await http.post(
|
|
Uri.parse(_ragUrl),
|
|
headers: headers,
|
|
body: jsonEncode(body),
|
|
);
|
|
|
|
if (response.statusCode >= 200 && response.statusCode < 300) {
|
|
final data = jsonDecode(response.body);
|
|
|
|
String outputText = '';
|
|
List<dynamic> parsedSources = [];
|
|
String? audioUrl;
|
|
|
|
if (data is Map<String, dynamic>) {
|
|
outputText = (data['answer'] ??
|
|
data['output'] ??
|
|
data['response'] ??
|
|
data['text'] ??
|
|
data['result'] ??
|
|
'')
|
|
.toString();
|
|
|
|
if (data['sources'] != null && data['sources'] is List) {
|
|
parsedSources = List<dynamic>.from(data['sources'] as List);
|
|
}
|
|
|
|
final rawAudioUrl = (data['audioUrl'] ?? data['url']) as String?;
|
|
audioUrl = _getFullAudioUrl(rawAudioUrl);
|
|
} else if (data is String) {
|
|
outputText = data;
|
|
}
|
|
|
|
return AiRagResponse(
|
|
output: outputText.isNotEmpty ? outputText : 'پاسخی دریافت نشد',
|
|
sources: parsedSources,
|
|
audioUrl: audioUrl,
|
|
isSuccess: true,
|
|
);
|
|
} else {
|
|
return AiRagResponse(
|
|
output: 'خطا در دریافت پاسخ از سرور (${response.statusCode})',
|
|
sources: [],
|
|
isSuccess: false,
|
|
);
|
|
}
|
|
} catch (e) {
|
|
return AiRagResponse(
|
|
output: 'خطا در ارتباط با سرور: ${e.toString()}',
|
|
sources: [],
|
|
isSuccess: false,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
class AiRagResponse {
|
|
final String output;
|
|
final List<dynamic> sources;
|
|
final String? audioUrl;
|
|
final bool isSuccess;
|
|
|
|
AiRagResponse({
|
|
required this.output,
|
|
required this.sources,
|
|
this.audioUrl,
|
|
required this.isSuccess,
|
|
});
|
|
}
|
|
|