File size: 4,396 Bytes
9af7af9 856bafd fad3187 9af7af9 8551660 9af7af9 8551660 856bafd 8551660 856bafd fad3187 8551660 9af7af9 8551660 9af7af9 856bafd fad3187 856bafd fad3187 856bafd 9af7af9 856bafd 9af7af9 856bafd 9af7af9 856bafd 9af7af9 856bafd ecd21e2 856bafd 9af7af9 fad3187 ecd21e2 9af7af9 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | import { describe, it, expect, vi } from 'vitest';
import { runGenerator } from '../src/generator/generator_core.mjs';
describe('generator_core.mjs (thinking generator)', () => {
it('includes question and context in the prompt and parses JSON output', async () => {
const fakeContext = [
{ content: 'First context chunk' },
{ content: 'Second context chunk' },
];
const provider = {
generate: vi.fn(async (prompt) => {
// Prompt should contain the question
expect(prompt).toContain('What is love?');
// And the context chunks (we expect {{CONTEXT}} is wired up)
expect(prompt).toContain('First context chunk');
expect(prompt).toContain('Second context chunk');
// Return JSON output
return JSON.stringify({
reasoning: ['step A', 'step B'],
answer: 'Love is the recognition of shared being.',
confidence: 0.92,
evidence: ['quote (para #1)'],
});
}),
};
const result = await runGenerator('What is love?', fakeContext, provider);
expect(provider.generate).toHaveBeenCalledOnce();
expect(result.question).toBe('What is love?');
expect(result.context).toHaveLength(2);
expect(result.raw).toContain('step A');
expect(result.answer).toBe('Love is the recognition of shared being.');
expect(result.thought).toContain('step A');
expect(result.confidence).toBeCloseTo(0.92);
});
it('extracts thought and answer correctly when <think> block is present', async () => {
const fakeContext = [{ content: 'ctx' }];
const provider = {
generate: vi.fn(async () => {
return `<think>
Step 1: Read the context carefully.
Step 2: Identify the relevant statements.
Step 3: Synthesize an answer.
</think>
The final answer derived from the context.`;
}),
};
const result = await runGenerator(
'Test question?',
fakeContext,
provider,
);
expect(result.raw).toContain('<think>');
expect(result.thought).toContain('Step 1:');
expect(result.thought).toContain('Step 3:');
expect(result.answer).toBe('The final answer derived from the context.');
});
it('handles output without <think> block gracefully', async () => {
const fakeContext = [{ content: 'ctx' }];
const provider = {
generate: vi.fn(async () => {
// No <think> tags at all
return 'Just a direct answer with no visible reasoning.';
}),
};
const result = await runGenerator(
'Another question?',
fakeContext,
provider,
);
expect(result.raw).toBe('Just a direct answer with no visible reasoning.');
// No JSON or think tags means thought falls back to raw
expect(result.thought).toBe('Just a direct answer with no visible reasoning.');
expect(result.answer).toBe('Just a direct answer with no visible reasoning.');
});
it('parses Qwen answer block and preserves thinking object', async () => {
const fakeContext = [{ content: 'ctx' }];
const provider = {
generate: vi.fn(async () => ({
response: `<|thought|>step1<|end_of_thought|>\n<|answer|>\nConfidence: High\nAnswer: Supported answer\nEvidence: ["quote1 (loc1)", "quote2 (loc2)"]\nLimitations: None\n<|end_of_answer|>`,
thinking: { steps: ['t1', 't2'] },
})),
};
const result = await runGenerator('Test?', fakeContext, provider);
expect(result.thought).toEqual({ steps: ['t1', 't2'] });
expect(result.answer).toBe('Supported answer');
expect(result.confidence).toBe('High');
expect(result.evidence).toEqual(['quote1 (loc1)', 'quote2 (loc2)']);
expect(result.limitations).toBe('None');
});
it('parses legacy reasoning tags without answer block', async () => {
const fakeContext = [{ content: 'ctx' }];
const provider = {
generate: vi.fn(async () =>
`<understanding>step A</understanding>\n<reasoning_chain>step B</reasoning_chain>\nConfidence: Medium\nAnswer: Legacy answer\nEvidence: ["ev1 (loc)"]\nLimitations: None`
),
};
const result = await runGenerator('Test?', fakeContext, provider);
expect(typeof result.thought).toBe('string');
expect(result.answer).toBe('Legacy answer');
expect(result.confidence).toBe('Medium');
expect(result.evidence).toEqual(['ev1 (loc)']);
expect(result.limitations).toBe('None');
});
});
|