Skip to content

Commit 0a4386b

Browse files
authored
Merge pull request #2 from kellertobias/allow-png-invoices-openai
feat: Allow PNG/Image uploads for AI Invoice Analysis
2 parents e301f6d + 37d5521 commit 0a4386b

File tree

2 files changed

+413
-295
lines changed

2 files changed

+413
-295
lines changed

src/backend/services/llm.service.spec.ts

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,102 @@ describe('LLMService', () => {
115115
'OpenAI API key not configured',
116116
);
117117
});
118+
119+
it('should handle image attachments correctly using image_url', async () => {
120+
mockCreate.mockResolvedValueOnce({
121+
choices: [{ message: { content: 'Image analysis' } }],
122+
usage: { prompt_tokens: 10, completion_tokens: 5, total_tokens: 15 },
123+
});
124+
const config: LLMConfig = {
125+
provider: 'openai',
126+
apiKey: 'test-key',
127+
model: 'gpt-4-vision',
128+
};
129+
const service = new LLMService(
130+
new MockConfigService(config) as unknown as ConfigService,
131+
);
132+
133+
const request: LLMRequest = {
134+
prompt: 'Analyze this image',
135+
files: [
136+
{
137+
name: 'test.png',
138+
content: Buffer.from('fake-image-data'),
139+
mimeType: 'image/png',
140+
},
141+
],
142+
};
143+
144+
await service.sendRequest(request);
145+
146+
expect(mockCreate).toHaveBeenCalledWith(
147+
expect.objectContaining({
148+
messages: expect.arrayContaining([
149+
expect.objectContaining({
150+
role: 'user',
151+
content: [
152+
{
153+
type: 'image_url',
154+
image_url: {
155+
url: `data:image/png;base64,${Buffer.from('fake-image-data').toString('base64')}`,
156+
},
157+
},
158+
],
159+
}),
160+
]),
161+
}),
162+
);
163+
expect(mockFilesCreate).not.toHaveBeenCalled();
164+
});
165+
166+
it('should handle PDF attachments correctly using file upload', async () => {
167+
mockCreate.mockResolvedValueOnce({
168+
choices: [{ message: { content: 'PDF analysis' } }],
169+
usage: { prompt_tokens: 10, completion_tokens: 5, total_tokens: 15 },
170+
});
171+
mockFilesCreate.mockResolvedValueOnce({ id: 'file-123' });
172+
173+
const config: LLMConfig = {
174+
provider: 'openai',
175+
apiKey: 'test-key',
176+
model: 'gpt-4',
177+
};
178+
const service = new LLMService(
179+
new MockConfigService(config) as unknown as ConfigService,
180+
);
181+
182+
const request: LLMRequest = {
183+
prompt: 'Analyze this PDF',
184+
files: [
185+
{
186+
name: 'test.pdf',
187+
content: Buffer.from('fake-pdf-data'),
188+
mimeType: 'application/pdf',
189+
},
190+
],
191+
};
192+
193+
await service.sendRequest(request);
194+
195+
expect(mockFilesCreate).toHaveBeenCalled();
196+
expect(mockCreate).toHaveBeenCalledWith(
197+
expect.objectContaining({
198+
messages: expect.arrayContaining([
199+
expect.objectContaining({
200+
role: 'user',
201+
content: [
202+
{
203+
type: 'file',
204+
file: {
205+
file_id: 'file-123',
206+
},
207+
},
208+
],
209+
}),
210+
]),
211+
}),
212+
);
213+
});
118214
});
119215

120216
describe('Anthropic provider', () => {

0 commit comments

Comments
 (0)