didvan-app/lib/services/ai_rag_service.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,
});
}