feat(learn): an assistant reads PDFs' pages, and sees images the person chooses or approves
ADR 0021, D12: text first. Lookups find a studyset's PDFs and read a page's text as PDFium extracts it. An assistant that reads images is offered a card's images as chips, and may ask to see a card's image or a PDF's page drawn whole; the conversation asks the person each time (Show it, Don't show) and sends nothing meanwhile. Images go only as png, jpeg, gif or webp of at most 5 MB, are never kept in a turn, and a follow-up goes without them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
cca10e855e
commit
2b7d04fd70
1 changed files with 2030 additions and 77 deletions
|
|
@ -1,3 +1,5 @@
|
|||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/assistant/model/assistant_conversation.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/assistant/model/assistant_prompt.dart';
|
||||
|
|
@ -67,6 +69,59 @@ void main() {
|
|||
});
|
||||
});
|
||||
|
||||
group('an image chosen (D12)', () {
|
||||
final bowl = LlmImage(
|
||||
mediaType: 'image/png',
|
||||
bytes: Uint8List.fromList([1, 2, 3]),
|
||||
);
|
||||
const image = AssistantPart(
|
||||
kind: AssistantPartKind.image,
|
||||
text: 'asset-bowl',
|
||||
number: 2,
|
||||
);
|
||||
|
||||
test('goes labelled, the image after its label', () {
|
||||
final message = questionMessage(
|
||||
'What is it?',
|
||||
const [
|
||||
image,
|
||||
],
|
||||
images: {'asset-bowl': bowl},
|
||||
);
|
||||
|
||||
expect(message.parts, hasLength(3));
|
||||
expect((message.parts[1] as LlmText).text, "\n\nThe card's image 2:\n");
|
||||
expect(message.parts[2], same(bowl));
|
||||
});
|
||||
|
||||
test('that cannot be had is said to be missing', () {
|
||||
final message = questionMessage('What is it?', const [image]);
|
||||
|
||||
expect(_texts(message).last, "\n\nThe card's image 2:\n$imageNotHad");
|
||||
});
|
||||
|
||||
test('is left as a mark once answered, read back as the part it was', () {
|
||||
final question = questionMessage(
|
||||
'What is it?',
|
||||
const [
|
||||
image,
|
||||
],
|
||||
images: {'asset-bowl': bowl},
|
||||
);
|
||||
final answer = LlmMessage.assistant(const [LlmText('A bowl.')]);
|
||||
|
||||
final kept = withoutImages([question, answer]);
|
||||
|
||||
expect(kept.last, same(answer));
|
||||
expect(_texts(kept.first).last, imageNotKept);
|
||||
final asked = askedIn(kept.first);
|
||||
expect(asked.question, 'What is it?');
|
||||
expect(asked.parts, [
|
||||
const AssistantPart(kind: AssistantPartKind.image, text: '', number: 2),
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
group('the system prompt', () {
|
||||
test('offers nothing to look up where only what is ticked goes', () {
|
||||
final prompt = systemPrompt(const AssistantScope());
|
||||
|
|
|
|||
Loading…
Reference in a new issue