1
1
using NUnit . Framework ;
2
+ using OpenAI . Files ;
2
3
using OpenAI . Responses ;
3
4
using OpenAI . Tests . Utility ;
5
+ using OpenAI . VectorStores ;
4
6
using System ;
5
7
using System . ClientModel ;
8
+ using System . ClientModel . Primitives ;
6
9
using System . Collections . Generic ;
7
10
using System . Linq ;
8
11
using System . Text ;
@@ -335,5 +338,72 @@ public async Task MCPToolWithDisallowedTools()
335
338
Assert . That ( response . OutputItems . OfType < McpToolCallItem > ( ) . ToList ( ) , Has . Count . EqualTo ( 0 ) ) ;
336
339
}
337
340
341
+ [ Test ]
342
+ public async Task FileSearch ( )
343
+ {
344
+ OpenAIFileClient fileClient = GetTestClient < OpenAIFileClient > ( TestScenario . Files ) ;
345
+ OpenAIFile testFile = await fileClient . UploadFileAsync (
346
+ BinaryData . FromString ( """
347
+ Travis's favorite food is pizza.
348
+ """ ) ,
349
+ "test_favorite_foods.txt" ,
350
+ FileUploadPurpose . UserData ) ;
351
+ Validate ( testFile ) ;
352
+
353
+ VectorStoreClient vscClient = GetTestClient < VectorStoreClient > ( TestScenario . VectorStores ) ;
354
+ VectorStore vectorStore = await vscClient . CreateVectorStoreAsync (
355
+ new VectorStoreCreationOptions ( )
356
+ {
357
+ FileIds = { testFile . Id } ,
358
+ } ) ;
359
+ Validate ( vectorStore ) ;
360
+
361
+ OpenAIResponseClient client = GetTestClient ( ) ;
362
+
363
+ OpenAIResponse response = await client . CreateResponseAsync (
364
+ "Using the file search tool, what's Travis's favorite food?" ,
365
+ new ResponseCreationOptions ( )
366
+ {
367
+ Tools =
368
+ {
369
+ ResponseTool . CreateFileSearchTool ( vectorStoreIds : [ vectorStore . Id ] ) ,
370
+ }
371
+ } ) ;
372
+ Assert . That ( response . OutputItems ? . Count , Is . EqualTo ( 2 ) ) ;
373
+ FileSearchCallResponseItem fileSearchCall = response . OutputItems [ 0 ] as FileSearchCallResponseItem ;
374
+ Assert . That ( fileSearchCall , Is . Not . Null ) ;
375
+ Assert . That ( fileSearchCall ? . Status , Is . EqualTo ( FileSearchCallStatus . Completed ) ) ;
376
+ Assert . That ( fileSearchCall ? . Queries , Has . Count . GreaterThan ( 0 ) ) ;
377
+ MessageResponseItem message = response . OutputItems [ 1 ] as MessageResponseItem ;
378
+ Assert . That ( message , Is . Not . Null ) ;
379
+ ResponseContentPart messageContentPart = message . Content ? . FirstOrDefault ( ) ;
380
+ Assert . That ( messageContentPart , Is . Not . Null ) ;
381
+ Assert . That ( messageContentPart . Text , Does . Contain ( "pizza" ) ) ;
382
+ Assert . That ( messageContentPart . OutputTextAnnotations , Is . Not . Null . And . Not . Empty ) ;
383
+ FileCitationMessageAnnotation annotation = messageContentPart . OutputTextAnnotations [ 0 ] as FileCitationMessageAnnotation ;
384
+ Assert . That ( annotation . FileId , Is . EqualTo ( testFile . Id ) ) ;
385
+ Assert . That ( annotation . Index , Is . GreaterThan ( 0 ) ) ;
386
+
387
+ await foreach ( ResponseItem inputItem in client . GetResponseInputItemsAsync ( response . Id ) )
388
+ {
389
+ Console . WriteLine ( ModelReaderWriter . Write ( inputItem ) . ToString ( ) ) ;
390
+ }
391
+ }
392
+
393
+ private List < string > FileIdsToDelete = [ ] ;
394
+ private List < string > VectorStoreIdsToDelete = [ ] ;
395
+
396
+ private void Validate < T > ( T input ) where T : class
397
+ {
398
+ if ( input is OpenAIFile file )
399
+ {
400
+ FileIdsToDelete . Add ( file . Id ) ;
401
+ }
402
+ if ( input is VectorStore vectorStore )
403
+ {
404
+ VectorStoreIdsToDelete . Add ( vectorStore . Id ) ;
405
+ }
406
+ }
407
+
338
408
private static OpenAIResponseClient GetTestClient ( string overrideModel = null ) => GetTestClient < OpenAIResponseClient > ( TestScenario . Responses , overrideModel ) ;
339
409
}
0 commit comments