Get and build prompt from local JSON file
Here we map our AI actions to the prompt from the JSON file to be able to use them.
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"prompts": [
|
||||
{
|
||||
"name": "test-prompt",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "You are a test assistant."
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "INSTRUCTION:\nTest instruction.\n\nTEXT:\n{{input}}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "test-prompt-with-task",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "You are a test assistant with task."
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "INSTRUCTION:\n{{task}}\n\nTEXT:\n{{input}}"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:scribe/scribe/ai/domain/model/prompt_data.dart';
|
||||
import 'package:scribe/scribe/ai/data/model/ai_message.dart';
|
||||
|
||||
void main() {
|
||||
group('PromptData', () {
|
||||
test('fromJson should parse prompts correctly', () {
|
||||
// Arrange
|
||||
final jsonData = {
|
||||
"prompts": [
|
||||
{
|
||||
"name": "test-prompt-1",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "System message 1"
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "User message 1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "test-prompt-2",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "System message 2"
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "User message 2"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// Act
|
||||
final promptData = PromptData.fromJson(jsonData);
|
||||
|
||||
// Assert
|
||||
expect(promptData.prompts.length, 2);
|
||||
expect(promptData.prompts.first.name, 'test-prompt-1');
|
||||
expect(promptData.prompts.last.name, 'test-prompt-2');
|
||||
expect(promptData.prompts.first.messages.length, 2);
|
||||
expect(promptData.prompts.last.messages.length, 2);
|
||||
});
|
||||
|
||||
test('fromJson should handle empty prompts list', () {
|
||||
// Arrange
|
||||
final jsonData = {
|
||||
"prompts": []
|
||||
};
|
||||
|
||||
// Act
|
||||
final promptData = PromptData.fromJson(jsonData);
|
||||
|
||||
// Assert
|
||||
expect(promptData.prompts.length, 0);
|
||||
});
|
||||
});
|
||||
|
||||
group('Prompt', () {
|
||||
test('fromJson should parse prompt correctly', () {
|
||||
// Arrange
|
||||
final jsonData = {
|
||||
"name": "test-prompt",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "System message"
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "User message with {{input}} placeholder"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// Act
|
||||
final prompt = Prompt.fromJson(jsonData);
|
||||
|
||||
// Assert
|
||||
expect(prompt.name, 'test-prompt');
|
||||
expect(prompt.messages.length, 2);
|
||||
expect(prompt.messages.first.role, 'system');
|
||||
expect(prompt.messages.first.content, 'System message');
|
||||
expect(prompt.messages.last.role, 'user');
|
||||
expect(prompt.messages.last.content, 'User message with {{input}} placeholder');
|
||||
});
|
||||
|
||||
test('buildPrompt should replace input placeholder correctly', () {
|
||||
// Arrange
|
||||
final messages = [
|
||||
const AIMessage(role: 'system', content: 'System message'),
|
||||
const AIMessage(role: 'user', content: 'User message with {{input}} placeholder')
|
||||
];
|
||||
final prompt = Prompt(name: 'test-prompt', messages: messages);
|
||||
|
||||
// Act
|
||||
final result = prompt.buildPrompt('test input value');
|
||||
|
||||
// Assert
|
||||
expect(result.length, 2);
|
||||
expect(result.first.role, 'system');
|
||||
expect(result.first.content, 'System message');
|
||||
expect(result.last.role, 'user');
|
||||
expect(result.last.content, 'User message with test input value placeholder');
|
||||
});
|
||||
|
||||
test('buildPrompt should replace task placeholder when provided', () {
|
||||
// Arrange
|
||||
final messages = [
|
||||
const AIMessage(role: 'system', content: 'System message'),
|
||||
const AIMessage(role: 'user', content: 'Task: {{task}}, Input: {{input}}')
|
||||
];
|
||||
final prompt = Prompt(name: 'test-prompt', messages: messages);
|
||||
|
||||
// Act
|
||||
final result = prompt.buildPrompt('test input value', task: 'test task value');
|
||||
|
||||
// Assert
|
||||
expect(result.length, 2);
|
||||
expect(result.first.role, 'system');
|
||||
expect(result.first.content, 'System message');
|
||||
expect(result.last.role, 'user');
|
||||
expect(result.last.content, 'Task: test task value, Input: test input value');
|
||||
});
|
||||
|
||||
test('buildPrompt should not replace task placeholder when not provided', () {
|
||||
// Arrange
|
||||
final messages = [
|
||||
const AIMessage(role: 'system', content: 'System message'),
|
||||
const AIMessage(role: 'user', content: 'Task: {{task}}, Input: {{input}}')
|
||||
];
|
||||
final prompt = Prompt(name: 'test-prompt', messages: messages);
|
||||
|
||||
// Act
|
||||
final result = prompt.buildPrompt('test input value');
|
||||
|
||||
// Assert
|
||||
expect(result.length, 2);
|
||||
expect(result.first.role, 'system');
|
||||
expect(result.first.content, 'System message');
|
||||
expect(result.last.role, 'user');
|
||||
expect(result.last.content, 'Task: {{task}}, Input: test input value');
|
||||
});
|
||||
|
||||
test('buildPrompt should handle messages without placeholders', () {
|
||||
// Arrange
|
||||
final messages = [
|
||||
const AIMessage(role: 'system', content: 'System message'),
|
||||
const AIMessage(role: 'user', content: 'User message without placeholders')
|
||||
];
|
||||
final prompt = Prompt(name: 'test-prompt', messages: messages);
|
||||
|
||||
// Act
|
||||
final result = prompt.buildPrompt('test input', task: 'test task');
|
||||
|
||||
// Assert
|
||||
expect(result.length, 2);
|
||||
expect(result.last.content, 'User message without placeholders');
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:scribe/scribe/ai/domain/service/prompt_service.dart';
|
||||
import 'package:scribe/scribe/ai/domain/model/prompt_data.dart';
|
||||
import 'package:scribe/scribe/ai/data/model/ai_message.dart';
|
||||
|
||||
void main() {
|
||||
setUpAll(() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
});
|
||||
|
||||
group('PromptService', () {
|
||||
test('PromptService should be singleton', () {
|
||||
// Act
|
||||
final service1 = PromptService();
|
||||
final service2 = PromptService();
|
||||
|
||||
// Assert
|
||||
expect(service1, same(service2));
|
||||
});
|
||||
|
||||
test('buildPromptByName should build prompt with input text', () async {
|
||||
// Arrange
|
||||
final service = PromptService();
|
||||
|
||||
// Act - this will use the real prompts.json file
|
||||
final messages = await service.buildPromptByName('change-tone-casual', 'Hello, how are you?');
|
||||
|
||||
// Assert
|
||||
expect(messages.length, 2);
|
||||
expect(messages.first.role, 'system');
|
||||
expect(messages.last.role, 'user');
|
||||
expect(messages.last.content, contains('Hello, how are you?'));
|
||||
});
|
||||
|
||||
test('buildPromptByName should build prompt with input text and task', () async {
|
||||
// Arrange
|
||||
final service = PromptService();
|
||||
|
||||
// Act - this will use the real prompts.json file
|
||||
final messages = await service.buildPromptByName('custom-prompt-mail', 'Hello, how are you?', task: 'Make it more casual');
|
||||
|
||||
// Assert
|
||||
expect(messages.length, 2);
|
||||
expect(messages.first.role, 'system');
|
||||
expect(messages.last.role, 'user');
|
||||
expect(messages.last.content, contains('Hello, how are you?'));
|
||||
expect(messages.last.content, contains('Make it more casual'));
|
||||
});
|
||||
});
|
||||
|
||||
group('PromptService getPromptByName', () {
|
||||
test('getPromptByName should return correct prompt from data', () async {
|
||||
// Arrange
|
||||
final promptData = PromptData(
|
||||
prompts: [
|
||||
Prompt(
|
||||
name: 'test-prompt',
|
||||
messages: [
|
||||
const AIMessage(role: 'system', content: 'System message'),
|
||||
const AIMessage(role: 'user', content: 'User message with {{input}}')
|
||||
]
|
||||
)
|
||||
]
|
||||
);
|
||||
|
||||
// Act
|
||||
final prompt = promptData.prompts.firstWhere(
|
||||
(prompt) => prompt.name == 'test-prompt',
|
||||
orElse: () => throw Exception('Prompt not found: test-prompt'),
|
||||
);
|
||||
|
||||
// Assert
|
||||
expect(prompt.name, 'test-prompt');
|
||||
expect(prompt.messages.length, 2);
|
||||
});
|
||||
|
||||
test('getPromptByName should throw exception for non-existent prompt', () async {
|
||||
// Arrange
|
||||
final promptData = PromptData(
|
||||
prompts: [
|
||||
Prompt(
|
||||
name: 'test-prompt',
|
||||
messages: [
|
||||
const AIMessage(role: 'system', content: 'System message'),
|
||||
const AIMessage(role: 'user', content: 'User message')
|
||||
]
|
||||
)
|
||||
]
|
||||
);
|
||||
|
||||
// Act & Assert
|
||||
expect(
|
||||
() => promptData.prompts.firstWhere(
|
||||
(prompt) => prompt.name == 'non-existent-prompt',
|
||||
orElse: () => throw Exception('Prompt not found: non-existent-prompt'),
|
||||
),
|
||||
throwsException,
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user