Browse Source

Merge commit 'c9146f571e09f8b679e0284f91a3946387d5252a'

newdev_shunjiawei
lxm 1 year ago
parent
commit
31bf7f951a
  1. 2
      lib/data/models/message_model.dart
  2. 8
      lib/data/services/ai_service.dart
  3. 6
      lib/data/services/deapsound_ai_service.dart
  4. 6
      lib/data/services/kouzi_ai_service.dart
  5. 10
      lib/data/services/open_ai_service_adapter.dart
  6. 6
      lib/data/services/volcano_ai_service.dart
  7. 33
      lib/modules/chat/controllers/chat_controller.dart
  8. 23
      lib/modules/chat/views/chat_music_card.dart
  9. 5
      lib/modules/chat/views/chat_view.dart
  10. 3
      local_plugins/open_ai_service/android/src/main/kotlin/com/yunqiinnovation/open_ai_service/OpenAIServicePlugin.kt
  11. 46
      local_plugins/open_ai_service/lib/open_ai_service.dart

2
lib/data/models/message_model.dart

@ -55,4 +55,4 @@ class Message {
isLoading: isLoading ?? this.isLoading, isLoading: isLoading ?? this.isLoading,
); );
} }
} }

8
lib/data/services/ai_service.dart

@ -1,16 +1,16 @@
/// AI回复服务接口 /// AI回复服务接口
abstract class AiService { abstract class AiService {
/// 非流式输出方法 /// 非流式输出方法
Future<String> sendMessage({ Future<String> sendMessage({
required List<Map<String, String>> messages, required List<Map<String, String>> messages,
required String systemPrompt, String? systemPrompt,
String? userProperties,
}); });
/// 流式输出方法 /// 流式输出方法
Stream sendMessageStream({ Stream sendMessageStream({
required List<Map<String, String>> messages, required List<Map<String, String>> messages,
required String systemPrompt, String? systemPrompt,
String? userProperties,
}); });
} }

6
lib/data/services/deapsound_ai_service.dart

@ -17,7 +17,8 @@ class DeapsoundAIService implements AiService {
@override @override
Future<String> sendMessage({ Future<String> sendMessage({
required List<Map<String, String>> messages, required List<Map<String, String>> messages,
required String systemPrompt, String? systemPrompt,
String? userProperties,
}) async { }) async {
return ''; return '';
} }
@ -25,7 +26,8 @@ class DeapsoundAIService implements AiService {
@override @override
Stream sendMessageStream({ Stream sendMessageStream({
required List<Map<String, String>> messages, required List<Map<String, String>> messages,
required String systemPrompt, String? systemPrompt,
String? userProperties,
}) async* { }) async* {
final client = http.Client(); final client = http.Client();
final url = Uri.parse('https://api.deapsound.com/ai/funcchat'); final url = Uri.parse('https://api.deapsound.com/ai/funcchat');

6
lib/data/services/kouzi_ai_service.dart

@ -13,7 +13,8 @@ class KouziAIService implements AiService {
@override @override
Future<String> sendMessage({ Future<String> sendMessage({
required List<Map<String, String>> messages, required List<Map<String, String>> messages,
required String systemPrompt, String? systemPrompt,
String? userProperties,
}) async { }) async {
return ''; return '';
} }
@ -21,7 +22,8 @@ class KouziAIService implements AiService {
@override @override
Stream<String> sendMessageStream({ Stream<String> sendMessageStream({
required List<Map<String, String>> messages, required List<Map<String, String>> messages,
required String systemPrompt, String? systemPrompt,
String? userProperties,
}) async* { }) async* {
final client = http.Client(); final client = http.Client();
final url = Uri.parse('https://api.coze.cn/v3/chat'); final url = Uri.parse('https://api.coze.cn/v3/chat');

10
lib/data/services/open_ai_service_adapter.dart

@ -160,7 +160,8 @@ class OpenAIServiceAdapter implements AiService {
@override @override
Future<String> sendMessage({ Future<String> sendMessage({
required List<Map<String, String>> messages, required List<Map<String, String>> messages,
required String systemPrompt, String? systemPrompt,
String? userProperties,
}) async { }) async {
try { try {
// 在方法内直接转换 // 在方法内直接转换
@ -170,6 +171,8 @@ class OpenAIServiceAdapter implements AiService {
// 发送消息并获取回复 // 发送消息并获取回复
final response = await _openAIService.sendMessage( final response = await _openAIService.sendMessage(
messages: convertedMessages, messages: convertedMessages,
systemPrompt: systemPrompt,
userProperties: userProperties,
); );
return response; return response;
@ -183,7 +186,8 @@ class OpenAIServiceAdapter implements AiService {
@override @override
Stream sendMessageStream({ Stream sendMessageStream({
required List<Map<String, String>> messages, required List<Map<String, String>> messages,
required String systemPrompt, String? systemPrompt, //提示词
String? userProperties, //用户属性
}) async* { }) async* {
try { try {
// 在方法内直接转换 // 在方法内直接转换
@ -231,6 +235,8 @@ class OpenAIServiceAdapter implements AiService {
try { try {
started = await _openAIService.sendMessageStream( started = await _openAIService.sendMessageStream(
messages: convertedMessages, messages: convertedMessages,
systemPrompt: systemPrompt,
userProperties: userProperties,
); );
} catch (e) { } catch (e) {
printError(info: '启动消息流失败: $e'); printError(info: '启动消息流失败: $e');

6
lib/data/services/volcano_ai_service.dart

@ -35,7 +35,8 @@ class VolcanoAIService implements AiService {
@override @override
Future<String> sendMessage({ Future<String> sendMessage({
required List<Map<String, String>> messages, required List<Map<String, String>> messages,
required String systemPrompt, String? systemPrompt,
String? userProperties,
}) async { }) async {
final url = Uri.parse('$_baseUrl$_chatEndpoint'); final url = Uri.parse('$_baseUrl$_chatEndpoint');
@ -84,7 +85,8 @@ class VolcanoAIService implements AiService {
@override @override
Stream<String> sendMessageStream({ Stream<String> sendMessageStream({
required List<Map<String, String>> messages, required List<Map<String, String>> messages,
required String systemPrompt, String? systemPrompt,
String? userProperties,
}) async* { }) async* {
final url = Uri.parse('$_baseUrl$_chatEndpoint'); final url = Uri.parse('$_baseUrl$_chatEndpoint');

33
lib/modules/chat/controllers/chat_controller.dart

@ -418,7 +418,10 @@ class ChatController extends GetxController {
); );
_updateIntermediateMessage(meta: chunk); _updateIntermediateMessage(meta: chunk);
if (chunk['card_spotify'] != null) { if (chunk['card_spotify'] != null) {
play(chunk['card_spotify']); play_spotify(chunk['card_spotify']);
}
if (chunk['card_music'] != null) {
play_music(chunk['card_music']);
} }
} else if (chunk is String) { } else if (chunk is String) {
fullResponse += chunk; fullResponse += chunk;
@ -505,7 +508,31 @@ class ChatController extends GetxController {
} }
// 播放音乐 // 播放音乐
void play(Map card) async { void play_music(Map card) async {
try {
isPlay.value = false;
if (audiourl.value != card['url']) {
audiourl.value = '';
await player.setUrl(card['url']);
audiourl.value = card['url'];
player.play();
} else {
player.play();
}
isPlay.value = true;
} catch (e) {
Logger.error('加载异常: $e');
}
}
// 播放音乐
void pause_music() async {
await player.pause();
isPlay.value = false;
}
// 播放音乐
void play_spotify(Map card) async {
try { try {
await _spotifService.initialize(); await _spotifService.initialize();
_spotifService.play(card['url'] as String); _spotifService.play(card['url'] as String);
@ -517,7 +544,7 @@ class ChatController extends GetxController {
} }
// 暂停播放音乐 // 暂停播放音乐
void pause() async { void pause_spotify() async {
try { try {
_spotifService.pause(); _spotifService.pause();
isPlay.value = false; isPlay.value = false;

23
lib/modules/chat/views/chat_music_card.dart

@ -5,10 +5,11 @@ import 'package:get/get.dart';
import '../controllers/chat_controller.dart'; import '../controllers/chat_controller.dart';
class ChatMusicCard extends GetView<ChatController> { class ChatMusicCard extends GetView<ChatController> {
final int type;
final Map? data; final Map? data;
final bool isDarkMode; final bool isDarkMode;
const ChatMusicCard(this.data, this.isDarkMode, {super.key}); const ChatMusicCard(this.type, this.data, this.isDarkMode, {super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -47,7 +48,15 @@ class ChatMusicCard extends GetView<ChatController> {
controller.isPlay.value controller.isPlay.value
? GestureDetector( ? GestureDetector(
onTap: () { onTap: () {
controller.pause(); switch (type) {
case 0:
controller.pause_music();
break;
case 1:
controller.pause_spotify();
break;
default:
}
}, },
child: Stack( child: Stack(
alignment: Alignment.center, alignment: Alignment.center,
@ -61,7 +70,15 @@ class ChatMusicCard extends GetView<ChatController> {
) )
: GestureDetector( : GestureDetector(
onTap: () { onTap: () {
controller.play(data!); switch (type) {
case 0:
controller.play_music(data!);
break;
case 1:
controller.play_spotify(data!);
break;
default:
}
}, },
child: Container( child: Container(
width: 38.w, width: 38.w,

5
lib/modules/chat/views/chat_view.dart

@ -374,8 +374,11 @@ class ChatView extends GetView<ChatController> {
if (message.meta?['card_weather'] != null) { if (message.meta?['card_weather'] != null) {
box = WeatherDayCard(message.meta?['card_weather'], isDarkMode); box = WeatherDayCard(message.meta?['card_weather'], isDarkMode);
} }
if (message.meta?['card_music'] != null) {
box = ChatMusicCard(0, message.meta?['card_music'], isDarkMode);
}
if (message.meta?['card_spotify'] != null) { if (message.meta?['card_spotify'] != null) {
box = ChatMusicCard(message.meta?['card_spotify'], isDarkMode); box = ChatMusicCard(1, message.meta?['card_spotify'], isDarkMode);
} }
if (message.meta?['card_navigation'] != null) { if (message.meta?['card_navigation'] != null) {
box = ChatNavigationCard( box = ChatNavigationCard(

3
local_plugins/open_ai_service/android/src/main/kotlin/com/yunqiinnovation/open_ai_service/OpenAIServicePlugin.kt

@ -126,7 +126,6 @@ class OpenAIServicePlugin : FlutterPlugin, MethodCallHandler, StreamHandler {
"sendMessageStream" -> { "sendMessageStream" -> {
val messagesRaw = call.argument<List<Map<String, Any>>>("messages") ?: emptyList() val messagesRaw = call.argument<List<Map<String, Any>>>("messages") ?: emptyList()
// 检查事件接收器 // 检查事件接收器
if (eventSink == null) { if (eventSink == null) {
result.error("NO_EVENT_SINK", "没有可用的事件流接收器", null) result.error("NO_EVENT_SINK", "没有可用的事件流接收器", null)
@ -176,7 +175,7 @@ class OpenAIServicePlugin : FlutterPlugin, MethodCallHandler, StreamHandler {
mainHandler.post { mainHandler.post {
eventSink?.success(mapOf("type" to "functionCall", "content" to context,"meta" to meta.toString())) eventSink?.success(mapOf("type" to "functionCall", "content" to context,"meta" to meta.toString()))
} }
if (metaJsonObject.containsKey("card_spotify")) { if (metaJsonObject.containsKey("card_spotify") || metaJsonObject.containsKey("card_music")) {
mainHandler.post { mainHandler.post {
eventSink?.success(mapOf("type" to "complete")) eventSink?.success(mapOf("type" to "complete"))
} }

46
local_plugins/open_ai_service/lib/open_ai_service.dart

@ -195,12 +195,33 @@ class OpenAIService {
/// [messages] 消息列表 /// [messages] 消息列表
Future<String> sendMessage({ Future<String> sendMessage({
required List<Map<String, dynamic>> messages, required List<Map<String, dynamic>> messages,
String? systemPrompt, //提示词
String? userProperties, //用户属性
}) async { }) async {
try { try {
// 构建新的消息列表
final List<Map<String, dynamic>> updatedMessages = [];
// 如果有提示词,先添加 system role
if (systemPrompt != null && systemPrompt.isNotEmpty) {
updatedMessages.add({
'role': 'system',
'content': systemPrompt,
});
}
// 如果有用户属性,可以作为 user 的一个“隐式指令”传进去
if (userProperties != null && userProperties.isNotEmpty) {
updatedMessages.add({
'role': 'user',
'content': '【用户属性】$userProperties',
});
}
// 添加原始消息
updatedMessages.addAll(messages);
final result = await _channel.invokeMethod<String>( final result = await _channel.invokeMethod<String>(
'sendMessage', 'sendMessage',
{ {
'messages': messages, 'messages': updatedMessages,
}, },
); );
@ -221,12 +242,33 @@ class OpenAIService {
/// 返回一个布尔值,表示请求是否已开始 /// 返回一个布尔值,表示请求是否已开始
Future<bool> sendMessageStream({ Future<bool> sendMessageStream({
required List<Map<String, dynamic>> messages, required List<Map<String, dynamic>> messages,
String? systemPrompt, //提示词
String? userProperties, //用户属性
}) async { }) async {
try { try {
// 构建新的消息列表
final List<Map<String, dynamic>> updatedMessages = [];
// 如果有提示词,先添加 system role
if (systemPrompt != null && systemPrompt.isNotEmpty) {
updatedMessages.add({
'role': 'system',
'content': systemPrompt,
});
}
// 如果有用户属性,可以作为 user 的一个“隐式指令”传进去
if (userProperties != null && userProperties.isNotEmpty) {
updatedMessages.add({
'role': 'user',
'content': '【用户属性】$userProperties',
});
}
// 添加原始消息
updatedMessages.addAll(messages);
final result = await _channel.invokeMethod<bool>( final result = await _channel.invokeMethod<bool>(
'sendMessageStream', 'sendMessageStream',
{ {
'messages': messages, 'messages': updatedMessages,
}, },
); );

Loading…
Cancel
Save