176 lines
4.4 KiB
Markdown
176 lines
4.4 KiB
Markdown
|
|
# mnemo_cards_chat
|
||
|
|
|
||
|
|
A Flutter package providing chat functionality with LLM integration for mnemo_cards applications.
|
||
|
|
|
||
|
|
## Features
|
||
|
|
|
||
|
|
- 💬 **Text Chat**: Send and receive text messages with LLM
|
||
|
|
- 🎤 **Audio Messages**: Record and playback voice messages
|
||
|
|
- 🔄 **Reactive State**: State management with yx_state
|
||
|
|
- 🏗️ **Clean Architecture**: Modular design with dependency injection
|
||
|
|
- 🔌 **Extensible**: Abstract ChatRepository interface for different backends
|
||
|
|
|
||
|
|
## Installation
|
||
|
|
|
||
|
|
Add to your `pubspec.yaml`:
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
dependencies:
|
||
|
|
mnemo_cards_chat:
|
||
|
|
path: packages/mnemo_cards_chat
|
||
|
|
```
|
||
|
|
|
||
|
|
## Usage
|
||
|
|
|
||
|
|
### Basic Setup
|
||
|
|
|
||
|
|
```dart
|
||
|
|
import 'package:mnemo_cards_chat/mnemo_cards_chat.dart';
|
||
|
|
|
||
|
|
// 1. Implement ChatRepository for your backend
|
||
|
|
class MyChatRepository implements ChatRepository {
|
||
|
|
// Implement all ChatRepository methods
|
||
|
|
// e.g., sendTextMessage, getChatMessages, etc.
|
||
|
|
}
|
||
|
|
|
||
|
|
// 2. Create chat service
|
||
|
|
final chatService = ChatService(chatRepository: MyChatRepository());
|
||
|
|
|
||
|
|
// 3. Create state manager
|
||
|
|
final chatStateManager = ChatStateManager(chatService: chatService);
|
||
|
|
|
||
|
|
// 4. Use in your UI
|
||
|
|
// See ChatStateManager for available methods
|
||
|
|
```
|
||
|
|
|
||
|
|
### Dependency Injection with yx_scope
|
||
|
|
|
||
|
|
```dart
|
||
|
|
import 'package:yx_scope/yx_scope.dart';
|
||
|
|
import 'package:mnemo_cards_chat/mnemo_cards_chat.dart';
|
||
|
|
|
||
|
|
class ChatModule extends ScopeModule<UserScopeContainer> {
|
||
|
|
ChatModule(super.container);
|
||
|
|
|
||
|
|
// Chat repository adapter
|
||
|
|
late final chatRepositoryDep = dep(
|
||
|
|
() => ChatRepositoryAdapter(container.httpRepository),
|
||
|
|
);
|
||
|
|
|
||
|
|
// Chat service
|
||
|
|
late final chatServiceDep = dep(
|
||
|
|
() => ChatService(chatRepository: chatRepositoryDep.get),
|
||
|
|
);
|
||
|
|
|
||
|
|
// Chat state manager
|
||
|
|
late final chatStateManagerDep = dep(
|
||
|
|
() => ChatStateManager(chatService: chatServiceDep.get),
|
||
|
|
);
|
||
|
|
|
||
|
|
ChatStateManager get chatStateManager => chatStateManagerDep.get;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### State Management
|
||
|
|
|
||
|
|
```dart
|
||
|
|
// Initialize chat session
|
||
|
|
await chatStateManager.initializeChat('session_id');
|
||
|
|
|
||
|
|
// Send text message
|
||
|
|
await chatStateManager.sendTextMessage('Hello, world!');
|
||
|
|
|
||
|
|
// Send audio message
|
||
|
|
final audioData = Uint8List.fromList([...]);
|
||
|
|
await chatStateManager.sendAudioMessage(audioData, Duration(seconds: 5));
|
||
|
|
|
||
|
|
// Listen to state changes
|
||
|
|
chatStateManager.addListener(() {
|
||
|
|
final state = chatStateManager.state;
|
||
|
|
if (state is ChatStateLoaded) {
|
||
|
|
// Handle loaded state
|
||
|
|
print('Messages: ${state.messages.length}');
|
||
|
|
} else if (state is ChatStateError) {
|
||
|
|
// Handle error
|
||
|
|
print('Error: ${state.message}');
|
||
|
|
}
|
||
|
|
});
|
||
|
|
```
|
||
|
|
|
||
|
|
## Architecture
|
||
|
|
|
||
|
|
### Core Components
|
||
|
|
|
||
|
|
- **`ChatService`**: Business logic and API orchestration
|
||
|
|
- **`ChatStateManager`**: Reactive state management
|
||
|
|
- **`ChatRepository`**: Abstract interface for backend communication
|
||
|
|
- **Models**: Data structures for messages, sessions, and participants
|
||
|
|
|
||
|
|
### State Types
|
||
|
|
|
||
|
|
```dart
|
||
|
|
// Loading state
|
||
|
|
const ChatStateLoading()
|
||
|
|
|
||
|
|
// Loaded state with session data
|
||
|
|
ChatStateLoaded(
|
||
|
|
session: session,
|
||
|
|
messages: messages,
|
||
|
|
isSendingMessage: false,
|
||
|
|
errorMessage: null,
|
||
|
|
)
|
||
|
|
|
||
|
|
// Error state
|
||
|
|
ChatStateError('Failed to load chat')
|
||
|
|
```
|
||
|
|
|
||
|
|
## Models
|
||
|
|
|
||
|
|
### ChatMessage
|
||
|
|
Union type for different message types:
|
||
|
|
- `ChatMessage.text(TextMessage)` - Text messages
|
||
|
|
- `ChatMessage.audio(AudioMessage)` - Audio messages
|
||
|
|
|
||
|
|
### ChatParticipant
|
||
|
|
Represents chat participants:
|
||
|
|
- `ChatParticipant.user()` - Human users
|
||
|
|
- `ChatParticipant.assistant()` - AI assistants
|
||
|
|
|
||
|
|
### ChatSession
|
||
|
|
Represents chat conversation sessions with metadata.
|
||
|
|
|
||
|
|
## API Integration
|
||
|
|
|
||
|
|
Implement `ChatRepository` to connect with your backend:
|
||
|
|
|
||
|
|
```dart
|
||
|
|
abstract class ChatRepository {
|
||
|
|
Future<ChatBasicSession> createChatSession(CreateChatSessionRequest request);
|
||
|
|
Future<List<ChatBasicSession>> getChatSessions({int limit, String? afterSessionId});
|
||
|
|
Future<ChatBasicSession> getChatSession(String sessionId);
|
||
|
|
Future<ChatMessageResponse> sendTextMessage(SendTextMessageRequest request);
|
||
|
|
Future<ChatMessageResponse> sendAudioMessage(String sessionId, dynamic audioData, Duration duration, {String? fileName, String? mimeType});
|
||
|
|
Future<List<ChatMessageResponse>> getChatMessages(String sessionId, {int limit, String? beforeMessageId});
|
||
|
|
Future<ChatBasicSession> updateChatSession(String sessionId, Map<String, dynamic> updates);
|
||
|
|
Future<void> deleteChatSession(String sessionId);
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Testing
|
||
|
|
|
||
|
|
Run tests:
|
||
|
|
```bash
|
||
|
|
flutter test
|
||
|
|
```
|
||
|
|
|
||
|
|
## Contributing
|
||
|
|
|
||
|
|
1. Follow the existing code style
|
||
|
|
2. Add tests for new features
|
||
|
|
3. Update documentation
|
||
|
|
4. Ensure all tests pass
|
||
|
|
|
||
|
|
## License
|
||
|
|
|
||
|
|
This package is part of the mnemo_cards project.
|