2024-12-23 12:03:05 +08:00
|
|
|
|
import { existsSync } from 'node:fs';
|
|
|
|
|
import path from 'node:path';
|
2024-09-09 15:57:36 +08:00
|
|
|
|
import { AIActionType } from '@/ai-model/common';
|
2025-01-14 21:07:03 +08:00
|
|
|
|
import { call, callToGetJSONObject } from '@/ai-model/service-caller';
|
2024-12-20 15:18:52 +08:00
|
|
|
|
import { base64Encoded } from '@/image';
|
|
|
|
|
import dotenv from 'dotenv';
|
|
|
|
|
import { getFixture } from 'tests/utils';
|
2024-12-23 12:03:05 +08:00
|
|
|
|
import { beforeAll, describe, expect, it, vi } from 'vitest';
|
2024-12-20 15:18:52 +08:00
|
|
|
|
|
2025-02-07 14:55:52 +08:00
|
|
|
|
dotenv.config({
|
|
|
|
|
debug: true,
|
|
|
|
|
override: true,
|
|
|
|
|
});
|
|
|
|
|
|
2024-07-23 16:25:11 +08:00
|
|
|
|
vi.setConfig({
|
|
|
|
|
testTimeout: 20 * 1000,
|
|
|
|
|
});
|
2024-12-23 12:03:05 +08:00
|
|
|
|
[
|
|
|
|
|
'.env.qwen',
|
|
|
|
|
'.env.gemini',
|
|
|
|
|
'.env.doubao',
|
|
|
|
|
'.env.init_json',
|
|
|
|
|
'.env.anthropic',
|
|
|
|
|
'.env.openai',
|
2025-02-25 07:49:14 +01:00
|
|
|
|
'.env.ui-tars',
|
2024-12-23 12:03:05 +08:00
|
|
|
|
].forEach((envFile) => {
|
|
|
|
|
const configPath = path.resolve(__dirname, `../../${envFile}`);
|
|
|
|
|
if (!existsSync(configPath)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2024-09-09 15:57:36 +08:00
|
|
|
|
|
2025-02-25 07:49:14 +01:00
|
|
|
|
const isUiTars = envFile === '.env.ui-tars';
|
|
|
|
|
|
2024-12-23 14:38:07 +08:00
|
|
|
|
describe(`LLM service connectivity: ${envFile}`, () => {
|
|
|
|
|
beforeAll(() => {
|
|
|
|
|
const result = dotenv.config({
|
|
|
|
|
debug: true,
|
|
|
|
|
path: configPath,
|
|
|
|
|
override: true,
|
2024-12-23 12:03:05 +08:00
|
|
|
|
});
|
2024-12-23 14:38:07 +08:00
|
|
|
|
if (result.error) {
|
|
|
|
|
throw result.error;
|
|
|
|
|
}
|
|
|
|
|
});
|
2024-12-19 10:44:08 +08:00
|
|
|
|
|
2024-12-23 14:38:07 +08:00
|
|
|
|
it('text only', async () => {
|
2025-02-25 07:49:14 +01:00
|
|
|
|
const result = await call(
|
|
|
|
|
[
|
|
|
|
|
{
|
|
|
|
|
role: 'system',
|
|
|
|
|
content: 'Answer the question',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
role: 'user',
|
|
|
|
|
content:
|
|
|
|
|
'鲁迅认识周树人吗?回答我:1. 分析原因 2.回答:是/否/无效问题',
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
AIActionType.EXTRACT_DATA,
|
|
|
|
|
);
|
2024-12-23 14:38:07 +08:00
|
|
|
|
|
|
|
|
|
expect(result.content.length).toBeGreaterThan(1);
|
|
|
|
|
});
|
|
|
|
|
|
2025-02-25 07:49:14 +01:00
|
|
|
|
it.skipIf(isUiTars)('call to get json result', async () => {
|
2024-12-23 14:38:07 +08:00
|
|
|
|
const result = await callToGetJSONObject<{ answer: number }>(
|
|
|
|
|
[
|
2024-12-19 10:44:08 +08:00
|
|
|
|
{
|
2024-12-23 12:03:05 +08:00
|
|
|
|
role: 'system',
|
2024-12-23 14:38:07 +08:00
|
|
|
|
content: 'Answer the question with JSON: {answer: number}',
|
2024-12-19 10:44:08 +08:00
|
|
|
|
},
|
|
|
|
|
{
|
2024-12-23 12:03:05 +08:00
|
|
|
|
role: 'user',
|
2024-12-23 14:38:07 +08:00
|
|
|
|
content: '3 x 5 = ?',
|
2024-12-23 12:03:05 +08:00
|
|
|
|
},
|
2024-12-23 14:38:07 +08:00
|
|
|
|
],
|
2025-02-25 07:49:14 +01:00
|
|
|
|
AIActionType.INSPECT_ELEMENT,
|
|
|
|
|
);
|
|
|
|
|
expect(result.content).toEqual({ answer: 15 });
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it.skipIf(!isUiTars)('for ui-tars, call to get json result', async () => {
|
|
|
|
|
const result = await callToGetJSONObject<{ answer: number }>(
|
|
|
|
|
[
|
|
|
|
|
{
|
|
|
|
|
role: 'system',
|
|
|
|
|
content: `Answer the question
|
|
|
|
|
## Output Json String Format
|
|
|
|
|
\`\`\`
|
|
|
|
|
"{
|
|
|
|
|
"answer": <<is a number, the answer of the question>>,
|
|
|
|
|
}"
|
|
|
|
|
|
|
|
|
|
## Rules **MUST** follow
|
|
|
|
|
- Make sure to return **only** the JSON, with **no additional** text or explanations.
|
|
|
|
|
- You **MUST** strict follow up the **Output Json String Format**.
|
|
|
|
|
\`\`\`
|
|
|
|
|
`,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
role: 'user',
|
|
|
|
|
content: '3 x 5 = ?',
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
AIActionType.INSPECT_ELEMENT,
|
2024-12-23 14:38:07 +08:00
|
|
|
|
);
|
|
|
|
|
expect(result.content).toEqual({ answer: 15 });
|
|
|
|
|
});
|
2024-12-23 12:03:05 +08:00
|
|
|
|
|
2024-12-23 14:38:07 +08:00
|
|
|
|
it('image input', async () => {
|
|
|
|
|
const imagePath = getFixture('baidu.png');
|
2025-02-25 07:49:14 +01:00
|
|
|
|
const result = await call(
|
|
|
|
|
[
|
|
|
|
|
{
|
|
|
|
|
role: 'user',
|
|
|
|
|
content: [
|
|
|
|
|
{
|
|
|
|
|
type: 'text',
|
|
|
|
|
text: 'Describe this image in one sentence.',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
type: 'image_url',
|
|
|
|
|
image_url: {
|
|
|
|
|
url: base64Encoded(imagePath),
|
|
|
|
|
detail: 'high',
|
|
|
|
|
},
|
2024-12-23 14:38:07 +08:00
|
|
|
|
},
|
2025-02-25 07:49:14 +01:00
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
AIActionType.EXTRACT_DATA,
|
|
|
|
|
);
|
2024-12-23 12:03:05 +08:00
|
|
|
|
|
2024-12-23 14:38:07 +08:00
|
|
|
|
expect(result.content.length).toBeGreaterThan(10);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
2024-12-19 10:44:08 +08:00
|
|
|
|
|
2024-12-23 14:38:07 +08:00
|
|
|
|
describe('keep at least one test in each suite', () => {
|
|
|
|
|
it('test', () => {
|
|
|
|
|
expect(1).toBe(1);
|
|
|
|
|
});
|
2024-08-04 08:28:19 +08:00
|
|
|
|
});
|