216 lines
7.9 KiB
TypeScript
216 lines
7.9 KiB
TypeScript
import { expect, tap } from '@push.rocks/tapbundle';
|
|
import * as qenv from '@push.rocks/qenv';
|
|
import * as smartrequest from '@push.rocks/smartrequest';
|
|
import * as smartfile from '@push.rocks/smartfile';
|
|
|
|
const testQenv = new qenv.Qenv('./', './.nogit/');
|
|
|
|
import * as smartai from '../ts/index.js';
|
|
|
|
let anthropicProvider: smartai.AnthropicProvider;
|
|
|
|
tap.test('Anthropic: should create and start Anthropic provider', async () => {
|
|
anthropicProvider = new smartai.AnthropicProvider({
|
|
anthropicToken: await testQenv.getEnvVarOnDemand('ANTHROPIC_TOKEN'),
|
|
});
|
|
await anthropicProvider.start();
|
|
expect(anthropicProvider).toBeInstanceOf(smartai.AnthropicProvider);
|
|
});
|
|
|
|
tap.test('Anthropic: should create chat response', async () => {
|
|
const userMessage = 'What is the capital of France? Answer in one word.';
|
|
const response = await anthropicProvider.chat({
|
|
systemMessage: 'You are a helpful assistant. Be concise.',
|
|
userMessage: userMessage,
|
|
messageHistory: [],
|
|
});
|
|
console.log(`Anthropic Chat - User: ${userMessage}`);
|
|
console.log(`Anthropic Chat - Response: ${response.message}`);
|
|
|
|
expect(response.role).toEqual('assistant');
|
|
expect(response.message).toBeTruthy();
|
|
expect(response.message.toLowerCase()).toInclude('paris');
|
|
});
|
|
|
|
tap.test('Anthropic: should handle message history', async () => {
|
|
const messageHistory: smartai.ChatMessage[] = [
|
|
{ role: 'user', content: 'My name is Claude Test' },
|
|
{ role: 'assistant', content: 'Nice to meet you, Claude Test!' }
|
|
];
|
|
|
|
const response = await anthropicProvider.chat({
|
|
systemMessage: 'You are a helpful assistant with good memory.',
|
|
userMessage: 'What is my name?',
|
|
messageHistory: messageHistory,
|
|
});
|
|
|
|
console.log(`Anthropic Memory Test - Response: ${response.message}`);
|
|
expect(response.message.toLowerCase()).toInclude('claude test');
|
|
});
|
|
|
|
tap.test('Anthropic: should analyze coffee image with latte art', async () => {
|
|
// Test 1: Coffee image from Unsplash by Dani
|
|
const imagePath = './test/testimages/coffee-dani/coffee.jpg';
|
|
console.log(`Loading coffee image from: ${imagePath}`);
|
|
|
|
const imageBuffer = await smartfile.fs.toBuffer(imagePath);
|
|
console.log(`Image loaded, size: ${imageBuffer.length} bytes`);
|
|
|
|
const result = await anthropicProvider.vision({
|
|
image: imageBuffer,
|
|
prompt: 'Describe this coffee image. What do you see in terms of the cup, foam pattern, and overall composition?'
|
|
});
|
|
|
|
console.log(`Anthropic Vision (Coffee) - Result: ${result}`);
|
|
expect(result).toBeTruthy();
|
|
expect(typeof result).toEqual('string');
|
|
expect(result.toLowerCase()).toInclude('coffee');
|
|
// The image has a heart pattern in the latte art
|
|
const mentionsLatte = result.toLowerCase().includes('heart') ||
|
|
result.toLowerCase().includes('latte') ||
|
|
result.toLowerCase().includes('foam');
|
|
expect(mentionsLatte).toBeTrue();
|
|
});
|
|
|
|
tap.test('Anthropic: should analyze laptop/workspace image', async () => {
|
|
// Test 2: Laptop image from Unsplash by Nicolas Bichon
|
|
const imagePath = './test/testimages/laptop-nicolas/laptop.jpg';
|
|
console.log(`Loading laptop image from: ${imagePath}`);
|
|
|
|
const imageBuffer = await smartfile.fs.toBuffer(imagePath);
|
|
console.log(`Image loaded, size: ${imageBuffer.length} bytes`);
|
|
|
|
const result = await anthropicProvider.vision({
|
|
image: imageBuffer,
|
|
prompt: 'Describe the technology and workspace setup in this image. What devices and equipment can you see?'
|
|
});
|
|
|
|
console.log(`Anthropic Vision (Laptop) - Result: ${result}`);
|
|
expect(result).toBeTruthy();
|
|
expect(typeof result).toEqual('string');
|
|
// Should mention laptop, computer, keyboard, or desk
|
|
const mentionsTech = result.toLowerCase().includes('laptop') ||
|
|
result.toLowerCase().includes('computer') ||
|
|
result.toLowerCase().includes('keyboard') ||
|
|
result.toLowerCase().includes('desk');
|
|
expect(mentionsTech).toBeTrue();
|
|
});
|
|
|
|
tap.test('Anthropic: should analyze receipt/document image', async () => {
|
|
// Test 3: Receipt image from Unsplash by Annie Spratt
|
|
const imagePath = './test/testimages/receipt-annie/receipt.jpg';
|
|
console.log(`Loading receipt image from: ${imagePath}`);
|
|
|
|
const imageBuffer = await smartfile.fs.toBuffer(imagePath);
|
|
console.log(`Image loaded, size: ${imageBuffer.length} bytes`);
|
|
|
|
const result = await anthropicProvider.vision({
|
|
image: imageBuffer,
|
|
prompt: 'What type of document is this? Can you identify any text or numbers visible in the image?'
|
|
});
|
|
|
|
console.log(`Anthropic Vision (Receipt) - Result: ${result}`);
|
|
expect(result).toBeTruthy();
|
|
expect(typeof result).toEqual('string');
|
|
// Should mention receipt, document, text, or paper
|
|
const mentionsDocument = result.toLowerCase().includes('receipt') ||
|
|
result.toLowerCase().includes('document') ||
|
|
result.toLowerCase().includes('text') ||
|
|
result.toLowerCase().includes('paper');
|
|
expect(mentionsDocument).toBeTrue();
|
|
});
|
|
|
|
tap.test('Anthropic: should document a PDF', async () => {
|
|
const pdfUrl = 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf';
|
|
const pdfResponse = await smartrequest.SmartRequest.create()
|
|
.url(pdfUrl)
|
|
.get();
|
|
|
|
const result = await anthropicProvider.document({
|
|
systemMessage: 'Classify the document. Only the following answers are allowed: "invoice", "bank account statement", "contract", "test document", "other". The answer should only contain the keyword for machine use.',
|
|
userMessage: 'Classify this document.',
|
|
messageHistory: [],
|
|
pdfDocuments: [Buffer.from(await pdfResponse.arrayBuffer())],
|
|
});
|
|
|
|
console.log(`Anthropic Document - Result:`, result);
|
|
expect(result).toBeTruthy();
|
|
expect(result.message).toBeTruthy();
|
|
});
|
|
|
|
tap.test('Anthropic: should handle complex document analysis', async () => {
|
|
// Test with the demo PDF if it exists
|
|
const pdfPath = './.nogit/demo_without_textlayer.pdf';
|
|
let pdfBuffer: Uint8Array;
|
|
|
|
try {
|
|
pdfBuffer = await smartfile.fs.toBuffer(pdfPath);
|
|
} catch (error) {
|
|
// If the file doesn't exist, use the dummy PDF
|
|
console.log('Demo PDF not found, using dummy PDF instead');
|
|
const pdfUrl = 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf';
|
|
const pdfResponse = await smartrequest.SmartRequest.create()
|
|
.url(pdfUrl)
|
|
.get();
|
|
pdfBuffer = Buffer.from(await pdfResponse.arrayBuffer());
|
|
}
|
|
|
|
const result = await anthropicProvider.document({
|
|
systemMessage: `
|
|
Analyze this document and provide a JSON response with the following structure:
|
|
{
|
|
"documentType": "string",
|
|
"hasText": boolean,
|
|
"summary": "string"
|
|
}
|
|
`,
|
|
userMessage: 'Analyze this document.',
|
|
messageHistory: [],
|
|
pdfDocuments: [pdfBuffer],
|
|
});
|
|
|
|
console.log(`Anthropic Complex Document Analysis:`, result);
|
|
expect(result).toBeTruthy();
|
|
expect(result.message).toBeTruthy();
|
|
});
|
|
|
|
tap.test('Anthropic: should handle errors gracefully', async () => {
|
|
// Test with invalid message (empty)
|
|
let errorCaught = false;
|
|
|
|
try {
|
|
await anthropicProvider.chat({
|
|
systemMessage: '',
|
|
userMessage: '',
|
|
messageHistory: [],
|
|
});
|
|
} catch (error) {
|
|
errorCaught = true;
|
|
console.log('Expected error caught:', error.message);
|
|
}
|
|
|
|
// Anthropic might handle empty messages, so we don't assert error
|
|
console.log(`Error handling test - Error caught: ${errorCaught}`);
|
|
});
|
|
|
|
tap.test('Anthropic: audio should throw not supported error', async () => {
|
|
let errorCaught = false;
|
|
|
|
try {
|
|
await anthropicProvider.audio({
|
|
message: 'This should fail'
|
|
});
|
|
} catch (error) {
|
|
errorCaught = true;
|
|
expect(error.message).toInclude('not yet supported');
|
|
}
|
|
|
|
expect(errorCaught).toBeTrue();
|
|
});
|
|
|
|
tap.test('Anthropic: should stop the provider', async () => {
|
|
await anthropicProvider.stop();
|
|
console.log('Anthropic provider stopped successfully');
|
|
});
|
|
|
|
export default tap.start(); |