Add chat preference extraction on shared ingest
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:relationship_saver/features/local/chat_preference_extractor.dart';
|
||||
import 'package:relationship_saver/features/local/local_models.dart';
|
||||
|
||||
void main() {
|
||||
const ChatPreferenceExtractor extractor = ChatPreferenceExtractor();
|
||||
|
||||
test('extracts prefer-over like/dislike signals', () {
|
||||
final List<ExtractedPreferenceSignalCandidate> result = extractor.extract(
|
||||
'I prefer tea over coffee, especially at night.',
|
||||
);
|
||||
|
||||
expect(
|
||||
result.any(
|
||||
(ExtractedPreferenceSignalCandidate item) =>
|
||||
item.key == 'drink:tea' &&
|
||||
item.polarity == PreferenceSignalPolarity.like,
|
||||
),
|
||||
isTrue,
|
||||
);
|
||||
expect(
|
||||
result.any(
|
||||
(ExtractedPreferenceSignalCandidate item) =>
|
||||
item.key == 'drink:coffee' &&
|
||||
item.polarity == PreferenceSignalPolarity.dislike,
|
||||
),
|
||||
isTrue,
|
||||
);
|
||||
});
|
||||
|
||||
test('extracts positive and negative statements with categories', () {
|
||||
final List<ExtractedPreferenceSignalCandidate> result = extractor.extract(
|
||||
"I love bookstores and I don't like loud clubs.",
|
||||
);
|
||||
|
||||
expect(
|
||||
result.any(
|
||||
(ExtractedPreferenceSignalCandidate item) =>
|
||||
item.category == 'hobby' &&
|
||||
item.polarity == PreferenceSignalPolarity.like,
|
||||
),
|
||||
isTrue,
|
||||
);
|
||||
expect(
|
||||
result.any(
|
||||
(ExtractedPreferenceSignalCandidate item) =>
|
||||
item.category == 'environment' &&
|
||||
item.polarity == PreferenceSignalPolarity.dislike,
|
||||
),
|
||||
isTrue,
|
||||
);
|
||||
});
|
||||
|
||||
test('extracts allergy as high-confidence dislike signal', () {
|
||||
final List<ExtractedPreferenceSignalCandidate> result = extractor.extract(
|
||||
'I am allergic to peanuts, please remember that.',
|
||||
);
|
||||
|
||||
final ExtractedPreferenceSignalCandidate signal = result.firstWhere(
|
||||
(ExtractedPreferenceSignalCandidate item) => item.key == 'health:peanuts',
|
||||
);
|
||||
expect(signal.polarity, PreferenceSignalPolarity.dislike);
|
||||
expect(signal.confidence, greaterThan(0.9));
|
||||
});
|
||||
}
|
||||
@@ -226,6 +226,57 @@ void main() {
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'ingestSharedMessage extracts chat-derived preference signals',
|
||||
() async {
|
||||
final ProviderContainer container = _createContainer();
|
||||
addTearDown(container.dispose);
|
||||
|
||||
await container.read(localRepositoryProvider.future);
|
||||
|
||||
final SharedMessageIngestResult result = await container
|
||||
.read(localRepositoryProvider.notifier)
|
||||
.ingestSharedMessage(
|
||||
const SharedMessageIngestInput(
|
||||
sourceApp: 'whatsapp',
|
||||
sourceDisplayName: 'Nora Diaz',
|
||||
sourceUserId: 'wa:nora_001',
|
||||
messageText:
|
||||
"I prefer tea over coffee and I don't like loud clubs.",
|
||||
),
|
||||
);
|
||||
|
||||
final LocalDataState after = await container.read(
|
||||
localRepositoryProvider.future,
|
||||
);
|
||||
final List<PersonPreferenceSignal> signals = after.preferenceSignals
|
||||
.where(
|
||||
(PersonPreferenceSignal signal) =>
|
||||
signal.personId == result.profileId,
|
||||
)
|
||||
.toList(growable: false);
|
||||
|
||||
expect(signals, isNotEmpty);
|
||||
expect(
|
||||
signals.any(
|
||||
(PersonPreferenceSignal signal) =>
|
||||
signal.key == 'drink:tea' &&
|
||||
signal.polarity == PreferenceSignalPolarity.like &&
|
||||
signal.status == PreferenceSignalStatus.inferred,
|
||||
),
|
||||
isTrue,
|
||||
);
|
||||
expect(
|
||||
signals.any(
|
||||
(PersonPreferenceSignal signal) =>
|
||||
signal.key == 'drink:coffee' &&
|
||||
signal.polarity == PreferenceSignalPolarity.dislike,
|
||||
),
|
||||
isTrue,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'queues near-match conflict and then uses fingerprint mapping for follow-up shares',
|
||||
() async {
|
||||
|
||||
Reference in New Issue
Block a user