Interfejs Gemini API umożliwia generowanie wspomagane wyszukiwaniem (RAG) za pomocą narzędzia wyszukiwania plików. Wyszukiwarka plików importuje, dzieli na części i indeksuje dane, aby umożliwić szybkie wyszukiwanie odpowiednich informacji na podstawie podanego promptu. Te informacje są następnie wykorzystywane jako kontekst dla modelu, co pozwala mu udzielać dokładniejszych i trafniejszych odpowiedzi. Wyszukiwanie plików może też oferować funkcje multimodalne z wektorami dystrybucyjnymi tekstu obsługiwanymi przez gemini-embedding-001 oraz wektorami dystrybucyjnymi obrazów i multimodalnymi obsługiwanymi przez gemini-embedding-2.
Przechowywanie plików i generowanie osadzania w momencie wysyłania zapytania jest bezpłatne. Płacisz tylko za tworzenie osadzania podczas pierwszego indeksowania plików oraz za normalne koszty tokenów wejściowych i wyjściowych modelu Gemini. Ten nowy model rozliczeń sprawia, że narzędzie do wyszukiwania plików jest łatwiejsze i bardziej opłacalne w tworzeniu i skalowaniu. Szczegółowe informacje znajdziesz w sekcji Ceny.
Przesyłanie bezpośrednio do sklepu File Search
Ten przykład pokazuje, jak przesłać plik bezpośrednio do wyszukiwarki plików:
Python
from google import genai
from google.genai import types
import time
client = genai.Client()
file_search_store = client.file_search_stores.create(
config={
'display_name': 'your-fileSearchStore-name',
'embedding_model': 'models/gemini-embedding-2'
}
)
operation = client.file_search_stores.upload_to_file_search_store(
file='sample.txt',
file_search_store_name=file_search_store.name,
config={
'display_name' : 'display-file-name',
}
)
while not operation.done:
time.sleep(5)
operation = client.operations.get(operation)
interaction = client.interactions.create(
model="gemini-3.8-flash",
input="Can you tell me about [insert question]",
tools=[{
"type": "file_search",
"file_search_store_names": [file_search_store.name]
}]
)
for step in interaction.steps:
if step.type == "model_output":
for content_block in step.content:
if content_block.type == "text":
print(content_block.text)
if content_block.annotations:
print("\nSources:")
for annotation in content_block.annotations:
if annotation.type == "file_citation":
print(f" - {annotation.file_name}: {annotation.source}")
JavaScript
import { GoogleGenAI } from '@google/genai';
const ai = new GoogleGenAI({});
async function run() {
const fileSearchStore = await ai.fileSearchStores.create({
config: {
displayName: 'your-fileSearchStore-name',
embeddingModel: 'models/gemini-embedding-2'
}
});
let operation = await ai.fileSearchStores.uploadToFileSearchStore({
file: 'file.txt',
fileSearchStoreName: fileSearchStore.name,
config: {
displayName: 'file-name',
}
});
while (!operation.done) {
await new Promise(resolve => setTimeout(resolve, 5000));
operation = await ai.operations.get({ operation });
}
const interaction = await ai.interactions.create({
model: "gemini-3.8-flash",
input: "Can you tell me about [insert question]",
tools: [{
type: "file_search",
file_search_store_names: [fileSearchStore.name]
}]
});
for (const step of interaction.steps) {
if (step.type === 'model_output') {
for (const contentBlock of step.content) {
if (contentBlock.type === 'text') {
console.log(contentBlock.text);
if (contentBlock.annotations) {
console.log("\nSources:");
for (const annotation of contentBlock.annotations) {
if (annotation.type === 'file_citation') {
console.log(` - ${annotation.file_name}: ${annotation.source}`);
}
}
}
}
}
}
}
}
run();
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.Annotation;
import com.google.genai.gaos.models.interactions.Content;
import com.google.genai.gaos.models.interactions.CreateModelInteraction;
import com.google.genai.gaos.models.interactions.FileCitation;
import com.google.genai.gaos.models.interactions.FileSearch;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Model;
import com.google.genai.gaos.models.interactions.ModelOutputStep;
import com.google.genai.gaos.models.interactions.Step;
import com.google.genai.gaos.models.interactions.TextContent;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import com.google.genai.types.CreateFileSearchStoreConfig;
import com.google.genai.types.FileSearchStore;
import com.google.genai.types.UploadToFileSearchStoreConfig;
import com.google.genai.types.UploadToFileSearchStoreOperation;
import java.util.Arrays;
Client client = new Client();
FileSearchStore fileSearchStore =
client.fileSearchStores.create(
CreateFileSearchStoreConfig.builder()
.displayName("your-fileSearchStore-name")
.embeddingModel("models/gemini-embedding-2")
.build());
UploadToFileSearchStoreOperation operation =
client.fileSearchStores.uploadToFileSearchStore(
fileSearchStore.name().get(),
"sample.txt",
UploadToFileSearchStoreConfig.builder().displayName("display-file-name").build());
while (!operation.done().orElse(false)) {
Thread.sleep(5000);
operation = client.operations.get(operation, null);
}
CreateModelInteraction params =
CreateModelInteraction.builder()
.model(Model.of("gemini-3.8-flash"))
.input(InteractionsInput.of("Can you tell me about [insert question]"))
.tools(
Arrays.asList(
FileSearch.builder()
.fileSearchStoreNames(Arrays.asList(fileSearchStore.name().get()))
.build()))
.build();
Interaction interaction =
client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
if (interaction.steps().isPresent()) {
for (Step step : interaction.steps().get()) {
if (step instanceof ModelOutputStep) {
ModelOutputStep outputStep = (ModelOutputStep) step;
if (outputStep.content().isPresent()) {
for (Content contentBlock : outputStep.content().get()) {
if (contentBlock instanceof TextContent) {
TextContent textContent = (TextContent) contentBlock;
System.out.println(textContent.text().orElse(""));
if (textContent.annotations().isPresent()
&& !textContent.annotations().get().isEmpty()) {
System.out.println("\nSources:");
for (Annotation annotation : textContent.annotations().get()) {
if (annotation instanceof FileCitation) {
FileCitation citation = (FileCitation) annotation;
System.out.printf(
" - %s: %s%n",
citation.fileName().orElse(""), citation.source().orElse(""));
}
}
}
}
}
}
}
}
}
Go
package main
import (
"context"
"fmt"
"log"
"time"
"google.golang.org/genai"
"google.golang.org/genai/interactions/models/interactions"
"google.golang.org/genai/interactions/models/operations"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
fileSearchStore, err := client.FileSearchStores.Create(ctx, &genai.CreateFileSearchStoreConfig{
DisplayName: "your-fileSearchStore-name",
EmbeddingModel: "models/gemini-embedding-2",
})
if err != nil {
log.Fatal(err)
}
operation, err := client.FileSearchStores.UploadToFileSearchStoreFromPath(
ctx,
"sample.txt",
fileSearchStore.Name,
&genai.UploadToFileSearchStoreConfig{
DisplayName: "display-file-name",
},
)
if err != nil {
log.Fatal(err)
}
for !operation.Done {
time.Sleep(5 * time.Second)
operation, err = client.Operations.GetUploadToFileSearchStoreOperation(ctx, operation, nil)
if err != nil {
log.Fatal(err)
}
}
resp, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
Body: operations.NewCreateInteractionRequestBody(
interactions.CreateModelInteraction{
Model: interactions.Model("gemini-3.8-flash"),
Input: interactions.NewInteractionsInput("Can you tell me about [insert question]"),
Tools: []interactions.Tool{
interactions.NewTool(interactions.FileSearch{
FileSearchStoreNames: []string{fileSearchStore.Name},
}),
},
},
),
})
if err != nil {
log.Fatal(err)
}
for _, step := range resp.Interaction.Steps {
if step.ModelOutputStep != nil {
for _, content := range step.ModelOutputStep.Content {
if content.TextContent != nil {
fmt.Println(content.TextContent.Text)
if len(content.TextContent.Annotations) > 0 {
fmt.Println("\nSources:")
for _, annotation := range content.TextContent.Annotations {
if annotation.FileCitation != nil {
c := annotation.FileCitation
fileName := ""
if c.FileName != nil {
fileName = *c.FileName
}
source := ""
if c.Source != nil {
source = *c.Source
}
fmt.Printf(" - %s: %s\n", fileName, source)
}
}
}
}
}
}
}
}
REST
# 1. Create a File Search store
curl -X POST "https://generativelanguage.googleapis.com/v1beta/fileSearchStores?key=$GEMINI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"displayName": "your-file-search-store-name",
"embeddingModel": "models/gemini-embedding-2"
}' > store_res.json
FILE_SEARCH_STORE_NAME=$(jq -r ".name" store_res.json)
# 2. Upload directly to File Search store using resumable upload
NUM_BYTES=$(wc -c < "sample.txt")
curl "https://generativelanguage.googleapis.com/upload/v1beta/fileSearchStores/$FILE_SEARCH_STORE_NAME:uploadToFileSearchStore?key=$GEMINI_API_KEY" \
-D upload-header.tmp \
-H "X-Goog-Upload-Protocol: resumable" \
-H "X-Goog-Upload-Command: start" \
-H "X-Goog-Upload-Header-Content-Length: $NUM_BYTES" \
-H "X-Goog-Upload-Header-Content-Type: text/plain" \
-H "Content-Type: application/json" \
-d '{"displayName": "sample.txt"}' 2> /dev/null
upload_url=$(grep -i "x-goog-upload-url: " upload-header.tmp | cut -d" " -f2 | tr -d "\r")
rm upload-header.tmp
curl "${upload_url}" \
-H "Content-Length: $NUM_BYTES" \
-H "X-Goog-Upload-Offset: 0" \
-H "X-Goog-Upload-Command: upload, finalize" \
--data-binary "@sample.txt" 2> /dev/null > upload_response.json
cat upload_response.json
# 3. Query using the File Search store
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-3.8-flash",
"input": "Can you tell me about [insert question]",
"tools": [{
"type": "file_search",
"file_search_store_names": ["'"$FILE_SEARCH_STORE_NAME"'"]
}]
}'
Więcej informacji znajdziesz w dokumentacji interfejsu API uploadToFileSearchStore.
Importowanie plików
Możesz też przesłać istniejący plik i zaimportować go do magazynu wyszukiwania plików:
Python
from google import genai
from google.genai import types
import time
client = genai.Client()
sample_file = client.files.upload(file='sample.txt', config={'display_name': 'display_file_name'})
file_search_store = client.file_search_stores.create(
config={
'display_name': 'your-fileSearchStore-name',
'embedding_model': 'models/gemini-embedding-2'
}
)
operation = client.file_search_stores.import_file(
file_search_store_name=file_search_store.name,
file_name=sample_file.name
)
while not operation.done:
time.sleep(5)
operation = client.operations.get(operation)
interaction = client.interactions.create(
model="gemini-3.8-flash",
input="Can you tell me about [insert question]",
tools=[{
"type": "file_search",
"file_search_store_names": [file_search_store.name]
}]
)
for step in interaction.steps:
if step.type == "model_output":
for content_block in step.content:
if content_block.type == "text":
print(content_block.text)
JavaScript
import { GoogleGenAI } from '@google/genai';
const ai = new GoogleGenAI({});
async function run() {
const sampleFile = await ai.files.upload({
file: 'sample.txt',
config: { displayName: 'file-name' }
});
const fileSearchStore = await ai.fileSearchStores.create({
config: {
displayName: 'your-fileSearchStore-name',
embeddingModel: 'models/gemini-embedding-2'
}
});
let operation = await ai.fileSearchStores.importFile({
fileSearchStoreName: fileSearchStore.name,
fileName: sampleFile.name
});
while (!operation.done) {
await new Promise(resolve => setTimeout(resolve, 5000));
operation = await ai.operations.get({ operation: operation });
}
const interaction = await ai.interactions.create({
model: "gemini-3.8-flash",
input: "Can you tell me about [insert question]",
tools: [{
type: "file_search",
file_search_store_names: [fileSearchStore.name]
}]
});
for (const step of interaction.steps) {
if (step.type === 'model_output') {
for (const contentBlock of step.content) {
if (contentBlock.type === 'text') {
console.log(contentBlock.text);
}
}
}
}
}
run();
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.Content;
import com.google.genai.gaos.models.interactions.CreateModelInteraction;
import com.google.genai.gaos.models.interactions.FileSearch;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Model;
import com.google.genai.gaos.models.interactions.ModelOutputStep;
import com.google.genai.gaos.models.interactions.Step;
import com.google.genai.gaos.models.interactions.TextContent;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import com.google.genai.types.CreateFileSearchStoreConfig;
import com.google.genai.types.File;
import com.google.genai.types.FileSearchStore;
import com.google.genai.types.ImportFileOperation;
import com.google.genai.types.UploadFileConfig;
import java.util.Arrays;
Client client = new Client();
File sampleFile =
client.files.upload(
"sample.txt", UploadFileConfig.builder().displayName("display_file_name").build());
FileSearchStore fileSearchStore =
client.fileSearchStores.create(
CreateFileSearchStoreConfig.builder()
.displayName("your-fileSearchStore-name")
.embeddingModel("models/gemini-embedding-2")
.build());
ImportFileOperation operation =
client.fileSearchStores.importFile(
fileSearchStore.name().get(), sampleFile.name().get(), null);
while (!operation.done().orElse(false)) {
Thread.sleep(5000);
operation = client.operations.get(operation, null);
}
CreateModelInteraction params =
CreateModelInteraction.builder()
.model(Model.of("gemini-3.8-flash"))
.input(InteractionsInput.of("Can you tell me about [insert question]"))
.tools(
Arrays.asList(
FileSearch.builder()
.fileSearchStoreNames(Arrays.asList(fileSearchStore.name().get()))
.build()))
.build();
Interaction interaction =
client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
if (interaction.steps().isPresent()) {
for (Step step : interaction.steps().get()) {
if (step instanceof ModelOutputStep) {
ModelOutputStep outputStep = (ModelOutputStep) step;
if (outputStep.content().isPresent()) {
for (Content contentBlock : outputStep.content().get()) {
if (contentBlock instanceof TextContent) {
TextContent textContent = (TextContent) contentBlock;
System.out.println(textContent.text().orElse(""));
}
}
}
}
}
}
Go
package main
import (
"context"
"fmt"
"log"
"time"
"google.golang.org/genai"
"google.golang.org/genai/interactions/models/interactions"
"google.golang.org/genai/interactions/models/operations"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
sampleFile, err := client.Files.UploadFromPath(ctx, "sample.txt", &genai.UploadFileConfig{
DisplayName: "display_file_name",
})
if err != nil {
log.Fatal(err)
}
fileSearchStore, err := client.FileSearchStores.Create(ctx, &genai.CreateFileSearchStoreConfig{
DisplayName: "your-fileSearchStore-name",
EmbeddingModel: "models/gemini-embedding-2",
})
if err != nil {
log.Fatal(err)
}
operation, err := client.FileSearchStores.ImportFile(ctx, fileSearchStore.Name, sampleFile.Name, nil)
if err != nil {
log.Fatal(err)
}
for !operation.Done {
time.Sleep(5 * time.Second)
operation, err = client.Operations.GetImportFileOperation(ctx, operation, nil)
if err != nil {
log.Fatal(err)
}
}
resp, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
Body: operations.NewCreateInteractionRequestBody(
interactions.CreateModelInteraction{
Model: interactions.Model("gemini-3.8-flash"),
Input: interactions.NewInteractionsInput("Can you tell me about [insert question]"),
Tools: []interactions.Tool{
interactions.NewTool(interactions.FileSearch{
FileSearchStoreNames: []string{fileSearchStore.Name},
}),
},
},
),
})
if err != nil {
log.Fatal(err)
}
for _, step := range resp.Interaction.Steps {
if step.ModelOutputStep != nil {
for _, content := range step.ModelOutputStep.Content {
if content.TextContent != nil {
fmt.Println(content.TextContent.Text)
}
}
}
}
}
REST
# 1. Upload file using the Files API
NUM_BYTES=$(wc -c < "sample.txt")
curl "https://generativelanguage.googleapis.com/upload/v1beta/files?key=$GEMINI_API_KEY" \
-D upload-header.tmp \
-H "X-Goog-Upload-Protocol: resumable" \
-H "X-Goog-Upload-Command: start" \
-H "X-Goog-Upload-Header-Content-Length: $NUM_BYTES" \
-H "X-Goog-Upload-Header-Content-Type: text/plain" \
-H "Content-Type: application/json" \
-d '{"file": {"displayName": "sample.txt"}}' 2> /dev/null
upload_url=$(grep -i "x-goog-upload-url: " upload-header.tmp | cut -d" " -f2 | tr -d "\r")
rm upload-header.tmp
curl "${upload_url}" \
-H "Content-Length: $NUM_BYTES" \
-H "X-Goog-Upload-Offset: 0" \
-H "X-Goog-Upload-Command: upload, finalize" \
--data-binary "@sample.txt" 2> /dev/null > file_info.json
FILE_NAME=$(jq -r ".file.name" file_info.json)
# 2. Create a File Search store
curl -X POST "https://generativelanguage.googleapis.com/v1beta/fileSearchStores?key=$GEMINI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"displayName": "your-file-search-store-name",
"embeddingModel": "models/gemini-embedding-2"
}' > store_res.json
FILE_SEARCH_STORE_NAME=$(jq -r ".name" store_res.json)
# 3. Import the file into the File Search store
curl -X POST "https://generativelanguage.googleapis.com/v1beta/fileSearchStores/$FILE_SEARCH_STORE_NAME:importFile?key=$GEMINI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"fileName": "'"$FILE_NAME"'"}'
# 4. Query using the File Search store
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-3.8-flash",
"input": "Can you tell me about [insert question]",
"tools": [{
"type": "file_search",
"file_search_store_names": ["'"$FILE_SEARCH_STORE_NAME"'"]
}]
}'
Więcej informacji znajdziesz w dokumentacji interfejsu API importFile.
Konfiguracja podziału na fragmenty
Gdy zaimportujesz plik do sklepu File Search, zostanie on automatycznie podzielony na części, osadzony, zindeksowany i przesłany do sklepu File Search. Jeśli potrzebujesz większej kontroli nad strategią dzielenia na części, możesz określić ustawienie chunking_config, aby ustawić maksymalną liczbę tokenów w każdej części i maksymalną liczbę nakładających się tokenów.
Python
from google import genai
from google.genai import types
import time
client = genai.Client()
operation = client.file_search_stores.upload_to_file_search_store(
file_search_store_name=file_search_store.name,
file='sample.txt',
config={
'chunking_config': {
'white_space_config': {
'max_tokens_per_chunk': 200,
'max_overlap_tokens': 20
}
}
}
)
while not operation.done:
time.sleep(5)
operation = client.operations.get(operation)
print("Custom chunking complete.")
JavaScript
import { GoogleGenAI } from '@google/genai';
const ai = new GoogleGenAI({});
let operation = await ai.fileSearchStores.uploadToFileSearchStore({
file: 'file.txt',
fileSearchStoreName: fileSearchStore.name,
config: {
displayName: 'file-name',
chunkingConfig: {
whiteSpaceConfig: {
maxTokensPerChunk: 200,
maxOverlapTokens: 20
}
}
}
});
while (!operation.done) {
await new Promise(resolve => setTimeout(resolve, 5000));
operation = await ai.operations.get({ operation });
}
console.log("Custom chunking complete.");
Java
import com.google.genai.Client;
import com.google.genai.types.ChunkingConfig;
import com.google.genai.types.UploadToFileSearchStoreConfig;
import com.google.genai.types.UploadToFileSearchStoreOperation;
import com.google.genai.types.WhiteSpaceConfig;
Client client = new Client();
UploadToFileSearchStoreOperation operation =
client.fileSearchStores.uploadToFileSearchStore(
"fileSearchStores/my-file-search-store",
"sample.txt",
UploadToFileSearchStoreConfig.builder()
.displayName("file-name")
.chunkingConfig(
ChunkingConfig.builder()
.whiteSpaceConfig(
WhiteSpaceConfig.builder()
.maxTokensPerChunk(200)
.maxOverlapTokens(20)
.build())
.build())
.build());
while (!operation.done().orElse(false)) {
Thread.sleep(5000);
operation = client.operations.get(operation, null);
}
System.out.println("Custom chunking complete.");
Go
package main
import (
"context"
"fmt"
"log"
"time"
"google.golang.org/genai"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
operation, err := client.FileSearchStores.UploadToFileSearchStoreFromPath(
ctx,
"sample.txt",
"fileSearchStores/my-file-search-store",
&genai.UploadToFileSearchStoreConfig{
DisplayName: "file-name",
ChunkingConfig: &genai.ChunkingConfig{
WhiteSpaceConfig: &genai.WhiteSpaceConfig{
MaxTokensPerChunk: genai.Ptr(int32(200)),
MaxOverlapTokens: genai.Ptr(int32(20)),
},
},
},
)
if err != nil {
log.Fatal(err)
}
for !operation.Done {
time.Sleep(5 * time.Second)
operation, err = client.Operations.GetUploadToFileSearchStoreOperation(ctx, operation, nil)
if err != nil {
log.Fatal(err)
}
}
fmt.Println("Custom chunking complete.")
}
REST
NUM_BYTES=$(wc -c < "sample.txt")
curl "https://generativelanguage.googleapis.com/upload/v1beta/fileSearchStores/$FILE_SEARCH_STORE_NAME:uploadToFileSearchStore?key=$GEMINI_API_KEY" \
-D upload-header.tmp \
-H "X-Goog-Upload-Protocol: resumable" \
-H "X-Goog-Upload-Command: start" \
-H "X-Goog-Upload-Header-Content-Length: $NUM_BYTES" \
-H "X-Goog-Upload-Header-Content-Type: text/plain" \
-H "Content-Type: application/json" \
-d '{
"displayName": "sample.txt",
"chunkingConfig": {
"whiteSpaceConfig": {
"maxTokensPerChunk": 200,
"maxOverlapTokens": 20
}
}
}' 2> /dev/null
upload_url=$(grep -i "x-goog-upload-url: " upload-header.tmp | cut -d" " -f2 | tr -d "\r")
rm upload-header.tmp
curl "${upload_url}" \
-H "Content-Length: $NUM_BYTES" \
-H "X-Goog-Upload-Offset: 0" \
-H "X-Goog-Upload-Command: upload, finalize" \
--data-binary "@sample.txt" 2> /dev/null > upload_response.json
cat upload_response.json
Aby użyć sklepu File Search, przekaż go jako narzędzie do metody interactions.create, jak pokazano w przykładach przesyłania i importowania.
Jak to działa
Wyszukiwanie plików wykorzystuje technikę zwaną wyszukiwaniem semantycznym, aby znaleźć informacje istotne dla prompta użytkownika. W przeciwieństwie do standardowego wyszukiwania opartego na słowach kluczowych wyszukiwanie semantyczne rozumie znaczenie i kontekst zapytania.
Podczas importowania pliku jest on przekształcany w reprezentacje numeryczne zwane wektorami dystrybucyjnymi, które odzwierciedlają znaczenie semantyczne przesłanej treści. Te wektory dystrybycyjne są przechowywane w specjalnej bazie danych wyszukiwania plików. Gdy wysyłasz zapytanie, jest ono również przekształcane w wektor. Następnie system przeprowadza wyszukiwanie plików, aby znaleźć najbardziej podobne i odpowiednie fragmenty dokumentów w magazynie wyszukiwania plików.
W przypadku osadzania nie ma czasu życia (TTL); są one przechowywane do momentu ręcznego usunięcia lub wycofania modelu. Pliki są jednak usuwane po 48 godzinach.
Oto opis procesu korzystania z interfejsu File Search
uploadToFileSearchStore API:
Utwórz magazyn wyszukiwania plików: magazyn wyszukiwania plików zawiera przetworzone dane z Twoich plików. Jest to stały kontener na wektory dystrybucyjne, na których będzie działać wyszukiwanie semantyczne.
Przesyłanie pliku i importowanie do magazynu wyszukiwania plików: możesz jednocześnie przesłać plik i zaimportować wyniki do magazynu wyszukiwania plików. Spowoduje to utworzenie tymczasowego obiektu
File, który jest odwołaniem do pierwotnego dokumentu. Dane są następnie dzielone na części, przekształcane w wektory dystrybucyjne wyszukiwania plików i indeksowane. ObiektFilezostanie usunięty po 48 godzinach, a dane zaimportowane do magazynu wyszukiwania plików będą przechowywane bezterminowo, dopóki nie zdecydujesz się ich usunąć.Zapytanie z wyszukiwaniem plików: na koniec używasz narzędzia
FileSearchw wywołaniugenerateContent. W konfiguracji narzędzia określaszFileSearchRetrievalResource, który wskazujeFileSearchStore, którego chcesz wyszukać. Informuje to model, że ma przeprowadzić wyszukiwanie semantyczne w tym konkretnym magazynie wyszukiwania plików, aby znaleźć odpowiednie informacje, na których może oprzeć swoją odpowiedź.
Na tym diagramie linia przerywana od Dokumentów do Modelu osadzania
(za pomocą gemini-embedding-001)
reprezentuje interfejs API uploadToFileSearchStore (z pominięciem Pamięci plików).
W przeciwnym razie użycie interfejsu Files API do oddzielnego tworzenia, a następnie importowania plików przenosi proces indeksowania z Dokumentów do pamięci plików, a potem do modelu osadzania.
Sklepy z wyszukiwarką plików
Magazyn wyszukiwania plików to kontener na wektory dystrybucyjne dokumentów. Surowe pliki przesłane za pomocą interfejsu File API są usuwane po 48 godzinach, ale dane zaimportowane do sklepu wyszukiwania plików są przechowywane bezterminowo, dopóki nie usuniesz ich ręcznie. Możesz utworzyć wiele magazynów wyszukiwania plików, aby uporządkować dokumenty. Interfejs API FileSearchStore umożliwia tworzenie, wyświetlanie, pobieranie i usuwanie magazynów wyszukiwania plików oraz zarządzanie nimi. Nazwy sklepów wyszukiwania plików mają zasięg globalny.
Oto kilka przykładów zarządzania magazynami wyszukiwania plików:
Python
file_search_store = client.file_search_stores.create(
config={
'display_name': 'myfilesearchstore123',
'embedding_model': 'models/gemini-embedding-2'
}
)
for store in client.file_search_stores.list():
print(store)
my_file_search_store = client.file_search_stores.get(name=file_search_store.name)
client.file_search_stores.delete(name=file_search_store.name, config={'force': True})
JavaScript
const fileSearchStore = await ai.fileSearchStores.create({
config: {
displayName: 'myfilesearchstore123',
embeddingModel: 'models/gemini-embedding-2'
}
});
const fileSearchStores = await ai.fileSearchStores.list();
for await (const store of fileSearchStores) {
console.log(store);
}
const myFileSearchStore = await ai.fileSearchStores.get({
name: fileSearchStore.name
});
await ai.fileSearchStores.delete({
name: fileSearchStore.name,
config: { force: true }
});
Java
import com.google.genai.Client;
import com.google.genai.types.CreateFileSearchStoreConfig;
import com.google.genai.types.DeleteFileSearchStoreConfig;
import com.google.genai.types.FileSearchStore;
Client client = new Client();
FileSearchStore fileSearchStore =
client.fileSearchStores.create(
CreateFileSearchStoreConfig.builder()
.displayName("myfilesearchstore123")
.embeddingModel("models/gemini-embedding-2")
.build());
for (FileSearchStore store : client.fileSearchStores.list(null)) {
System.out.println(store);
}
FileSearchStore myFileSearchStore =
client.fileSearchStores.get(fileSearchStore.name().get(), null);
client.fileSearchStores.delete(
fileSearchStore.name().get(), DeleteFileSearchStoreConfig.builder().force(true).build());
Go
package main
import (
"context"
"fmt"
"log"
"google.golang.org/genai"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
fileSearchStore, err := client.FileSearchStores.Create(ctx, &genai.CreateFileSearchStoreConfig{
DisplayName: "myfilesearchstore123",
EmbeddingModel: "models/gemini-embedding-2",
})
if err != nil {
log.Fatal(err)
}
for store, err := range client.FileSearchStores.All(ctx) {
if err != nil {
log.Fatal(err)
}
fmt.Println(store)
}
myFileSearchStore, err := client.FileSearchStores.Get(ctx, fileSearchStore.Name, nil)
if err != nil {
log.Fatal(err)
}
_ = myFileSearchStore
err = client.FileSearchStores.Delete(ctx, fileSearchStore.Name, &genai.DeleteFileSearchStoreConfig{
Force: genai.Ptr(true),
})
if err != nil {
log.Fatal(err)
}
}
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/fileSearchStores?key=${GEMINI_API_KEY}" \
-H "Content-Type: application/json" \
-d '{ "displayName": "My Store", "embedding_model": "models/gemini-embedding-2" }'
curl "https://generativelanguage.googleapis.com/v1beta/fileSearchStores?key=${GEMINI_API_KEY}"
curl "https://generativelanguage.googleapis.com/v1beta/fileSearchStores/myfilesearchstore123?key=${GEMINI_API_KEY}"
curl -X DELETE "https://generativelanguage.googleapis.com/v1beta/fileSearchStores/myfilesearchstore123?key=${GEMINI_API_KEY}"
Dokumenty wyszukiwania plików
Możesz zarządzać poszczególnymi dokumentami w magazynach plików za pomocą interfejsu File Search Documents API, aby list każdy dokument w magazynie wyszukiwania plików, get informacje o dokumencie i delete dokument według nazwy.
Python
for document_in_store in client.file_search_stores.documents.list(parent='fileSearchStores/myfilesearchstore123'):
print(document_in_store)
file_search_document = client.file_search_stores.documents.get(name='fileSearchStores/myfilesearchstore123/documents/sampletxt123')
print(file_search_document)
client.file_search_stores.documents.delete(name='fileSearchStores/myfilesearchstore123/documents/sampletxt123', config={'force': True})
JavaScript
const documents = await ai.fileSearchStores.documents.list({
parent: 'fileSearchStores/myfilesearchstore123'
});
for await (const doc of documents) {
console.log(doc);
}
const fileSearchDocument = await ai.fileSearchStores.documents.get({
name: 'fileSearchStores/myfilesearchstore123/documents/sampletxt123'
});
await ai.fileSearchStores.documents.delete({
name: 'fileSearchStores/myfilesearchstore123/documents/sampletxt123',
config: { force: true }
});
Java
import com.google.genai.Client;
import com.google.genai.types.DeleteDocumentConfig;
import com.google.genai.types.Document;
Client client = new Client();
for (Document documentInStore :
client.fileSearchStores.documents.list("fileSearchStores/myfilesearchstore123", null)) {
System.out.println(documentInStore);
}
Document fileSearchDocument =
client.fileSearchStores.documents.get(
"fileSearchStores/myfilesearchstore123/documents/sampletxt123", null);
System.out.println(fileSearchDocument);
client.fileSearchStores.documents.delete(
"fileSearchStores/myfilesearchstore123/documents/sampletxt123",
DeleteDocumentConfig.builder().force(true).build());
Go
package main
import (
"context"
"fmt"
"log"
"google.golang.org/genai"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
for documentInStore, err := range client.FileSearchStores.Documents.All(ctx, "fileSearchStores/myfilesearchstore123") {
if err != nil {
log.Fatal(err)
}
fmt.Println(documentInStore)
}
fileSearchDocument, err := client.FileSearchStores.Documents.Get(ctx, "fileSearchStores/myfilesearchstore123/documents/sampletxt123", nil)
if err != nil {
log.Fatal(err)
}
fmt.Println(fileSearchDocument)
err = client.FileSearchStores.Documents.Delete(ctx, "fileSearchStores/myfilesearchstore123/documents/sampletxt123", &genai.DeleteDocumentConfig{
Force: genai.Ptr(true),
})
if err != nil {
log.Fatal(err)
}
}
REST
curl "https://generativelanguage.googleapis.com/v1beta/fileSearchStores/myfilesearchstore123/documents?key=${GEMINI_API_KEY}"
curl "https://generativelanguage.googleapis.com/v1beta/fileSearchStores/myfilesearchstore123/documents/sampletxt123?key=${GEMINI_API_KEY}"
curl -X DELETE "https://generativelanguage.googleapis.com/v1beta/fileSearchStores/myfilesearchstore123/documents/sampletxt123?key=${GEMINI_API_KEY}&force=true"
Metadane pliku
Do plików możesz dodawać niestandardowe metadane, aby ułatwić ich filtrowanie lub zapewnić dodatkowy kontekst. Metadane to zbiór par klucz-wartość.
Python
op = client.file_search_stores.import_file(
file_search_store_name=file_search_store.name,
file_name=sample_file.name,
config={
'custom_metadata': [
{"key": "author", "string_value": "Robert Graves"},
{"key": "year", "numeric_value": 1934}
]
}
)
JavaScript
let operation = await ai.fileSearchStores.importFile({
fileSearchStoreName: fileSearchStore.name,
fileName: sampleFile.name,
config: {
customMetadata: [
{ key: "author", stringValue: "Robert Graves" },
{ key: "year", numericValue: 1934 }
]
}
});
Java
import com.google.genai.Client;
import com.google.genai.types.CustomMetadata;
import com.google.genai.types.ImportFileConfig;
import com.google.genai.types.ImportFileOperation;
import java.util.Arrays;
Client client = new Client();
ImportFileOperation op =
client.fileSearchStores.importFile(
"fileSearchStores/myfilesearchstore123",
"files/samplefile123",
ImportFileConfig.builder()
.customMetadata(
Arrays.asList(
CustomMetadata.builder().key("author").stringValue("Robert Graves").build(),
CustomMetadata.builder().key("year").numericValue(1934f).build()))
.build());
Go
package main
import (
"context"
"log"
"google.golang.org/genai"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
op, err := client.FileSearchStores.ImportFile(
ctx,
"fileSearchStores/myfilesearchstore123",
"files/samplefile123",
&genai.ImportFileConfig{
CustomMetadata: []*genai.CustomMetadata{
{Key: "author", StringValue: "Robert Graves"},
{Key: "year", NumericValue: genai.Ptr(float32(1934))},
},
},
)
if err != nil {
log.Fatal(err)
}
_ = op
}
Jest to przydatne, gdy masz wiele dokumentów w magazynie wyszukiwania plików i chcesz przeszukać tylko ich podzbiór.
Python
interaction = client.interactions.create(
model="gemini-3.8-flash",
input="Tell me about the book 'I, Claudius'",
tools=[{
"type": "file_search",
"file_search_store_names": [file_search_store.name],
"metadata_filter": 'author="Robert Graves"',
}]
)
for step in interaction.steps:
if step.type == "model_output":
for content_block in step.content:
if content_block.type == "text":
print(content_block.text)
JavaScript
const interaction = await ai.interactions.create({
model: "gemini-3.8-flash",
input: "Tell me about the book 'I, Claudius'",
tools: [{
type: "file_search",
file_search_store_names: [fileSearchStore.name],
metadata_filter: 'author="Robert Graves"',
}]
});
for (const step of interaction.steps) {
if (step.type === 'model_output') {
for (const contentBlock of step.content) {
if (contentBlock.type === 'text') {
console.log(contentBlock.text);
}
}
}
}
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.Content;
import com.google.genai.gaos.models.interactions.CreateModelInteraction;
import com.google.genai.gaos.models.interactions.FileSearch;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Model;
import com.google.genai.gaos.models.interactions.ModelOutputStep;
import com.google.genai.gaos.models.interactions.Step;
import com.google.genai.gaos.models.interactions.TextContent;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.util.Arrays;
Client client = new Client();
CreateModelInteraction params =
CreateModelInteraction.builder()
.model(Model.of("gemini-3.8-flash"))
.input(InteractionsInput.of("Tell me about the book 'I, Claudius'"))
.tools(
Arrays.asList(
FileSearch.builder()
.fileSearchStoreNames(Arrays.asList("fileSearchStores/myfilesearchstore123"))
.metadataFilter("author=\"Robert Graves\"")
.build()))
.build();
Interaction interaction =
client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
if (interaction.steps().isPresent()) {
for (Step step : interaction.steps().get()) {
if (step instanceof ModelOutputStep) {
ModelOutputStep outputStep = (ModelOutputStep) step;
if (outputStep.content().isPresent()) {
for (Content contentBlock : outputStep.content().get()) {
if (contentBlock instanceof TextContent) {
TextContent textContent = (TextContent) contentBlock;
System.out.println(textContent.text().orElse(""));
}
}
}
}
}
}
Go
package main
import (
"context"
"fmt"
"log"
"google.golang.org/genai"
"google.golang.org/genai/interactions/models/interactions"
"google.golang.org/genai/interactions/models/operations"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
resp, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
Body: operations.NewCreateInteractionRequestBody(
interactions.CreateModelInteraction{
Model: interactions.Model("gemini-3.8-flash"),
Input: interactions.NewInteractionsInput("Tell me about the book 'I, Claudius'"),
Tools: []interactions.Tool{
interactions.NewTool(interactions.FileSearch{
FileSearchStoreNames: []string{"fileSearchStores/myfilesearchstore123"},
MetadataFilter: genai.Ptr(`author="Robert Graves"`),
}),
},
},
),
})
if err != nil {
log.Fatal(err)
}
for _, step := range resp.Interaction.Steps {
if step.ModelOutputStep != nil {
for _, content := range step.ModelOutputStep.Content {
if content.TextContent != nil {
fmt.Println(content.TextContent.Text)
}
}
}
}
}
REST
curl "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H 'Content-Type: application/json' \
-X POST \
-d '{
"model": "gemini-3.8-flash",
"input": [{"type": "text", "text": "Tell me about the book I, Claudius"}],
"tools": [{
"type": "file_search",
"file_search_store_names": ["'$STORE_NAME'"],
"metadata_filter": "author = \"Robert Graves\""
}]
}' 2> /dev/null > response.json
cat response.json
Wskazówki dotyczące implementacji składni filtra listy dla metadata_filter znajdziesz na stronie google.aip.dev/160.
Multimodalne wyszukiwanie plików
Multimodalne wyszukiwanie plików umożliwia natywne umieszczanie i wyszukiwanie obrazów, co pozwala na tworzenie rozbudowanych, multimodalnych aplikacji RAG.
Konfigurowanie modelu wektora dystrybucyjnego
Podczas tworzenia FileSearchStore musisz zastąpić domyślny model wektorów dystrybucyjnych tylko tekstowych, aby używać modelu multimodalnego. Użyj models/gemini-embedding-2, aby przetwarzać zarówno tekst, jak i obrazy.
Python
store = client.file_search_stores.create(
config={
"display_name": "Multimodal Catalog",
"embedding_model": "models/gemini-embedding-2",
}
)
JavaScript
const fileSearchStore = await ai.fileSearchStores.create({
config: {
displayName: "Multimodal Catalog",
embeddingModel: "models/gemini-embedding-2",
},
});
Java
import com.google.genai.Client;
import com.google.genai.types.CreateFileSearchStoreConfig;
import com.google.genai.types.FileSearchStore;
Client client = new Client();
FileSearchStore store =
client.fileSearchStores.create(
CreateFileSearchStoreConfig.builder()
.displayName("Multimodal Catalog")
.embeddingModel("models/gemini-embedding-2")
.build());
Go
package main
import (
"context"
"log"
"google.golang.org/genai"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
store, err := client.FileSearchStores.Create(ctx, &genai.CreateFileSearchStoreConfig{
DisplayName: "Multimodal Catalog",
EmbeddingModel: "models/gemini-embedding-2",
})
if err != nil {
log.Fatal(err)
}
_ = store
}
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/fileSearchStores?key=$GEMINI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"display_name": "Multimodal Catalog",
"embedding_model": "models/gemini-embedding-2"
}'
Prześlij obrazy
Po utworzeniu magazynu z modelem wektorów dystrybucyjnych multimodalnych możesz przesyłać pliki graficzne bezpośrednio za pomocą tych samych interfejsów API do przesyłania, które opisano w sekcji Bezpośrednie przesyłanie do magazynu wyszukiwania plików lub Importowanie plików.
Wymagania dotyczące plików graficznych:
- Pliki graficzne mogą mieć rozdzielczość maksymalnie 4K x 4K pikseli.
- Obsługiwane formaty to PNG i JPEG.
Cytaty
Gdy korzystasz z wyszukiwania plików, odpowiedź modelu może zawierać cytaty wskazujące, które części przesłanych dokumentów zostały użyte do wygenerowania odpowiedzi. Pomaga to w weryfikacji informacji.
Informacje o cytatach znajdziesz w atrybucie annotations w blokach content kroku model_output w odpowiedzi.
Python
for step in interaction.steps:
if step.type == 'model_output':
for content in step.content:
if content.type == 'text' and content.annotations:
print(content.annotations)
JavaScript
for (const step of interaction.steps) {
if (step.type === 'model_output') {
for (const contentBlock of step.content) {
if (contentBlock.type === 'text' && contentBlock.annotations) {
console.log(JSON.stringify(contentBlock.annotations, null, 2));
}
}
}
}
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.Content;
import com.google.genai.gaos.models.interactions.CreateModelInteraction;
import com.google.genai.gaos.models.interactions.FileSearch;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Model;
import com.google.genai.gaos.models.interactions.ModelOutputStep;
import com.google.genai.gaos.models.interactions.Step;
import com.google.genai.gaos.models.interactions.TextContent;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.util.Arrays;
Client client = new Client();
CreateModelInteraction params =
CreateModelInteraction.builder()
.model(Model.of("gemini-3.8-flash"))
.input(InteractionsInput.of("Can you tell me about [insert question]"))
.tools(
Arrays.asList(
FileSearch.builder()
.fileSearchStoreNames(Arrays.asList("fileSearchStores/myfilesearchstore123"))
.build()))
.build();
Interaction interaction =
client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
if (interaction.steps().isPresent()) {
for (Step step : interaction.steps().get()) {
if (step instanceof ModelOutputStep) {
ModelOutputStep outputStep = (ModelOutputStep) step;
if (outputStep.content().isPresent()) {
for (Content content : outputStep.content().get()) {
if (content instanceof TextContent) {
TextContent textContent = (TextContent) content;
if (textContent.annotations().isPresent()) {
System.out.println(textContent.annotations().get());
}
}
}
}
}
}
}
Go
package main
import (
"context"
"fmt"
"log"
"google.golang.org/genai"
"google.golang.org/genai/interactions/models/interactions"
"google.golang.org/genai/interactions/models/operations"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
resp, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
Body: operations.NewCreateInteractionRequestBody(
interactions.CreateModelInteraction{
Model: interactions.Model("gemini-3.8-flash"),
Input: interactions.NewInteractionsInput("Can you tell me about [insert question]"),
Tools: []interactions.Tool{
interactions.NewTool(interactions.FileSearch{
FileSearchStoreNames: []string{"fileSearchStores/myfilesearchstore123"},
}),
},
},
),
})
if err != nil {
log.Fatal(err)
}
for _, step := range resp.Interaction.Steps {
if step.ModelOutputStep != nil {
for _, content := range step.ModelOutputStep.Content {
if content.TextContent != nil && len(content.TextContent.Annotations) > 0 {
fmt.Println(content.TextContent.Annotations)
}
}
}
}
}
REST
{
"steps": [
{
"type": "model_output",
"content": [
{
"type": "text",
"text": "...",
"annotations": [
{
"type": "file_citation",
"file_name": "sample.txt",
"source": "..."
}
]
}
]
}
]
}
Szczegółowe informacje o strukturze cytatów znajdziesz w dokumentacji API do interakcji.
Numery stron
Gdy używasz wyszukiwania plików w dokumentach, które mają strony (np. w plikach PDF), odpowiedź modelu może zawierać numer strony, na której znaleziono informacje.
Dostęp do tych informacji można uzyskać za pomocą atrybutu page_number adnotacji file_citation.
Python
for step in interaction.steps:
if step.type == "model_output":
for content in step.content:
if content.type == "text" and content.annotations:
for annotation in content.annotations:
if annotation.type == "file_citation" and annotation.page_number:
print(f"Cited Page: {annotation.page_number}")
JavaScript
for (const step of interaction.steps) {
if (step.type === 'model_output') {
for (const block of step.content) {
if (block.type === 'text' && block.annotations) {
for (const annotation of block.annotations) {
if (annotation.type === 'file_citation' && annotation.pageNumber) {
console.log(`Cited Page: ${annotation.pageNumber}`);
}
}
}
}
}
}
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.Annotation;
import com.google.genai.gaos.models.interactions.Content;
import com.google.genai.gaos.models.interactions.CreateModelInteraction;
import com.google.genai.gaos.models.interactions.FileCitation;
import com.google.genai.gaos.models.interactions.FileSearch;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Model;
import com.google.genai.gaos.models.interactions.ModelOutputStep;
import com.google.genai.gaos.models.interactions.Step;
import com.google.genai.gaos.models.interactions.TextContent;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.util.Arrays;
Client client = new Client();
CreateModelInteraction params =
CreateModelInteraction.builder()
.model(Model.of("gemini-3.8-flash"))
.input(InteractionsInput.of("Can you tell me about [insert question]"))
.tools(
Arrays.asList(
FileSearch.builder()
.fileSearchStoreNames(Arrays.asList("fileSearchStores/myfilesearchstore123"))
.build()))
.build();
Interaction interaction =
client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
if (interaction.steps().isPresent()) {
for (Step step : interaction.steps().get()) {
if (step instanceof ModelOutputStep) {
ModelOutputStep outputStep = (ModelOutputStep) step;
if (outputStep.content().isPresent()) {
for (Content content : outputStep.content().get()) {
if (content instanceof TextContent) {
TextContent textContent = (TextContent) content;
if (textContent.annotations().isPresent()) {
for (Annotation annotation : textContent.annotations().get()) {
if (annotation instanceof FileCitation) {
FileCitation citation = (FileCitation) annotation;
if (citation.pageNumber().isPresent()) {
System.out.println("Cited Page: " + citation.pageNumber().get());
}
}
}
}
}
}
}
}
}
}
Go
package main
import (
"context"
"fmt"
"log"
"google.golang.org/genai"
"google.golang.org/genai/interactions/models/interactions"
"google.golang.org/genai/interactions/models/operations"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
resp, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
Body: operations.NewCreateInteractionRequestBody(
interactions.CreateModelInteraction{
Model: interactions.Model("gemini-3.8-flash"),
Input: interactions.NewInteractionsInput("Can you tell me about [insert question]"),
Tools: []interactions.Tool{
interactions.NewTool(interactions.FileSearch{
FileSearchStoreNames: []string{"fileSearchStores/myfilesearchstore123"},
}),
},
},
),
})
if err != nil {
log.Fatal(err)
}
for _, step := range resp.Interaction.Steps {
if step.ModelOutputStep != nil {
for _, content := range step.ModelOutputStep.Content {
if content.TextContent != nil {
for _, annotation := range content.TextContent.Annotations {
if annotation.FileCitation != nil && annotation.FileCitation.PageNumber != nil {
fmt.Println("Cited Page:", *annotation.FileCitation.PageNumber)
}
}
}
}
}
}
}
REST
{
"steps": [
{
"type": "model_output",
"content": [
{
"type": "text",
"text": "...",
"annotations": [
{
"type": "file_citation",
"file_name": "document.pdf",
"page_number": 1,
"source": "..."
}
]
}
]
}
]
}
Cytowania w mediach
Gdy model odwołuje się do fragmentu obrazu podczas generowania, interfejs API zwraca w adnotacjach adnotację typu file_citation, która zawiera media_id. Możesz użyć tego identyfikatora, aby pobrać dokładny fragment obrazu, do którego odnosi się model. Ten identyfikator media_id jest trwały w przypadku wielu wywołań wyszukiwania, co pozwala na niezawodne pobieranie tego samego obrazu lub zapisywanie go w pamięci podręcznej przy użyciu identyfikatora.
Poniższy fragment kodu to przykład kroku odpowiedzi REST:
{
"type": "model_output",
"content": [
{
"type": "text",
"text": "...",
"annotations": [
{
"type": "file_citation",
"file_name": "product_image",
"media_id": "fileSearchStores/my-store-123/media/BlobId-456"
}
]
}
]
}
Poniższe fragmenty kodu pokazują, jak pobrać media_id i pobrać multimedia:
Python
for step in interaction.steps:
if step.type == "model_output":
for content in step.content:
if content.type == "text" and content.annotations:
for annotation in content.annotations:
if annotation.type == "file_citation" and annotation.media_id:
print(f"Cited Media ID: {annotation.media_id}")
blob_content = client.file_search_stores.download_media(
media_id=annotation.media_id
)
JavaScript
for (const step of interaction.steps) {
if (step.type === 'model_output') {
for (const block of step.content) {
if (block.type === 'text' && block.annotations) {
for (const annotation of block.annotations) {
if (annotation.type === 'file_citation' && annotation.mediaId) {
console.log(`Cited Media ID: ${annotation.mediaId}`);
const blobContent = await ai.fileSearchStores.downloadMedia(annotation.mediaId);
}
}
}
}
}
}
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.Annotation;
import com.google.genai.gaos.models.interactions.Content;
import com.google.genai.gaos.models.interactions.CreateModelInteraction;
import com.google.genai.gaos.models.interactions.FileCitation;
import com.google.genai.gaos.models.interactions.FileSearch;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Model;
import com.google.genai.gaos.models.interactions.ModelOutputStep;
import com.google.genai.gaos.models.interactions.Step;
import com.google.genai.gaos.models.interactions.TextContent;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.util.Arrays;
Client client = new Client();
CreateModelInteraction params =
CreateModelInteraction.builder()
.model(Model.of("gemini-3.8-flash"))
.input(InteractionsInput.of("Can you tell me about [insert question]"))
.tools(
Arrays.asList(
FileSearch.builder()
.fileSearchStoreNames(Arrays.asList("fileSearchStores/myfilesearchstore123"))
.build()))
.build();
Interaction interaction =
client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
if (interaction.steps().isPresent()) {
for (Step step : interaction.steps().get()) {
if (step instanceof ModelOutputStep) {
ModelOutputStep outputStep = (ModelOutputStep) step;
if (outputStep.content().isPresent()) {
for (Content content : outputStep.content().get()) {
if (content instanceof TextContent) {
TextContent textContent = (TextContent) content;
if (textContent.annotations().isPresent()) {
for (Annotation annotation : textContent.annotations().get()) {
if (annotation instanceof FileCitation) {
FileCitation citation = (FileCitation) annotation;
if (citation.mediaId().isPresent()) {
System.out.println("Cited Media ID: " + citation.mediaId().get());
byte[] blobContent =
client.fileSearchStores.downloadMedia(citation.mediaId().get(), null);
}
}
}
}
}
}
}
}
}
}
Go
package main
import (
"context"
"fmt"
"log"
"google.golang.org/genai"
"google.golang.org/genai/interactions/models/interactions"
"google.golang.org/genai/interactions/models/operations"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
resp, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
Body: operations.NewCreateInteractionRequestBody(
interactions.CreateModelInteraction{
Model: interactions.Model("gemini-3.8-flash"),
Input: interactions.NewInteractionsInput("Can you tell me about [insert question]"),
Tools: []interactions.Tool{
interactions.NewTool(interactions.FileSearch{
FileSearchStoreNames: []string{"fileSearchStores/myfilesearchstore123"},
}),
},
},
),
})
if err != nil {
log.Fatal(err)
}
for _, step := range resp.Interaction.Steps {
if step.ModelOutputStep != nil {
for _, content := range step.ModelOutputStep.Content {
if content.TextContent != nil {
for _, annotation := range content.TextContent.Annotations {
if annotation.FileCitation != nil && annotation.FileCitation.MediaID != nil {
fmt.Println("Cited Media ID:", *annotation.FileCitation.MediaID)
blobContent, err := client.FileSearchStores.DownloadMedia(ctx, *annotation.FileCitation.MediaID, nil)
if err != nil {
log.Fatal(err)
}
_ = blobContent
}
}
}
}
}
}
}
REST
curl -X GET "https://generativelanguage.googleapis.com/v1/fileSearchStores/my-store-123/media/BlobId-456" \
-H "x-goog-api-key: $GEMINI_API_KEY"
Niestandardowe metadane
Jeśli do plików dodano niestandardowe metadane, możesz uzyskać do nich dostęp w adnotacjach do odpowiedzi modelu. Jest to przydatne do przekazywania dodatkowego kontekstu (np. adresów URL, numerów stron lub autorów) z dokumentów źródłowych do logiki aplikacji. Każda adnotacja cytatu typu file_citation zawiera te niestandardowe metadane.
Python
interaction = client.interactions.create(
model="gemini-3.8-flash",
input="Tell me about [insert question]",
tools=[{
"type": "file_search",
"file_search_store_names": [file_search_store.name]
}]
)
for step in interaction.steps:
if step.type == "model_output":
for content_block in step.content:
if content_block.annotations:
for annotation in content_block.annotations:
print(annotation)
JavaScript
const interaction = await ai.interactions.create({
model: "gemini-3.8-flash",
input: "Tell me about [insert question]",
tools: [{
type: "file_search",
file_search_store_names: [fileSearchStore.name]
}]
});
for (const step of interaction.steps) {
if (step.type === 'model_output') {
for (const contentBlock of step.content) {
if (contentBlock.annotations) {
contentBlock.annotations.forEach((annotation) => {
console.log(annotation);
});
}
}
}
}
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.Annotation;
import com.google.genai.gaos.models.interactions.Content;
import com.google.genai.gaos.models.interactions.CreateModelInteraction;
import com.google.genai.gaos.models.interactions.FileSearch;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Model;
import com.google.genai.gaos.models.interactions.ModelOutputStep;
import com.google.genai.gaos.models.interactions.Step;
import com.google.genai.gaos.models.interactions.TextContent;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.util.Arrays;
Client client = new Client();
CreateModelInteraction params =
CreateModelInteraction.builder()
.model(Model.of("gemini-3.8-flash"))
.input(InteractionsInput.of("Tell me about [insert question]"))
.tools(
Arrays.asList(
FileSearch.builder()
.fileSearchStoreNames(Arrays.asList("fileSearchStores/myfilesearchstore123"))
.build()))
.build();
Interaction interaction =
client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
if (interaction.steps().isPresent()) {
for (Step step : interaction.steps().get()) {
if (step instanceof ModelOutputStep) {
ModelOutputStep outputStep = (ModelOutputStep) step;
if (outputStep.content().isPresent()) {
for (Content contentBlock : outputStep.content().get()) {
if (contentBlock instanceof TextContent) {
TextContent textContent = (TextContent) contentBlock;
if (textContent.annotations().isPresent()) {
for (Annotation annotation : textContent.annotations().get()) {
System.out.println(annotation);
}
}
}
}
}
}
}
}
Go
package main
import (
"context"
"fmt"
"log"
"google.golang.org/genai"
"google.golang.org/genai/interactions/models/interactions"
"google.golang.org/genai/interactions/models/operations"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
resp, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
Body: operations.NewCreateInteractionRequestBody(
interactions.CreateModelInteraction{
Model: interactions.Model("gemini-3.8-flash"),
Input: interactions.NewInteractionsInput("Tell me about [insert question]"),
Tools: []interactions.Tool{
interactions.NewTool(interactions.FileSearch{
FileSearchStoreNames: []string{"fileSearchStores/myfilesearchstore123"},
}),
},
},
),
})
if err != nil {
log.Fatal(err)
}
for _, step := range resp.Interaction.Steps {
if step.ModelOutputStep != nil {
for _, content := range step.ModelOutputStep.Content {
if content.TextContent != nil {
for _, annotation := range content.TextContent.Annotations {
fmt.Println(annotation)
}
}
}
}
}
}
REST
{
"steps": [
{
"type": "model_output",
"content": [
{
"type": "text",
"text": "...",
"annotations": [
{
"file_name": "...",
"source": "...",
"custom_metadata": [
{
"key": "author",
"string_value": "Robert Graves"
},
{
"key": "year",
"numeric_value": 1934
}
]
}
]
}
]
}
]
}
Uporządkowane dane wyjściowe
Począwszy od modeli Gemini 3, możesz łączyć narzędzie do wyszukiwania plików z ustrukturyzowanymi danymi wyjściowymi.
Python
from pydantic import BaseModel, Field
class Money(BaseModel):
amount: str = Field(description="The numerical part of the amount.")
currency: str = Field(description="The currency of amount.")
interaction = client.interactions.create(
model="gemini-3.8-flash",
input="What is the minimum hourly wage in Tokyo right now?",
tools=[{
"type": "file_search",
"file_search_store_names": [file_search_store.name]
}],
response_format={
"type": "text",
"mime_type": "application/json",
"schema": Money.model_json_schema()
},
)
result = Money.model_validate_json(interaction.output_text)
print(result)
JavaScript
import { z } from "zod";
const moneyJsonSchema = {
type: "object",
properties: {
amount: { type: "string", description: "The numerical part of the amount." },
currency: { type: "string", description: "The currency of amount." }
},
required: ["amount", "currency"]
};
const moneySchema = z.fromJSONSchema(moneyJsonSchema);
async function run() {
const interaction = await ai.interactions.create({
model: "gemini-3.8-flash",
input: "What is the minimum hourly wage in Tokyo right now?",
tools: [{
type: "file_search",
file_search_store_names: [fileSearchStore.name],
}],
response_format: {
type: 'text',
mime_type: 'application/json',
schema: moneyJsonSchema
},
});
const result = moneySchema.parse(JSON.parse(interaction.output_text));
console.log(result);
}
run();
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.CreateModelInteraction;
import com.google.genai.gaos.models.interactions.CreateModelInteractionResponseFormat;
import com.google.genai.gaos.models.interactions.FileSearch;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Model;
import com.google.genai.gaos.models.interactions.ResponseFormat;
import com.google.genai.gaos.models.interactions.TextResponseFormat;
import com.google.genai.gaos.models.interactions.TextResponseFormatMimeType;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
Client client = new Client();
Map<String, Object> properties = new HashMap<>();
Map<String, Object> amountProp = new HashMap<>();
amountProp.put("type", "string");
amountProp.put("description", "The numerical part of the amount.");
properties.put("amount", amountProp);
Map<String, Object> currencyProp = new HashMap<>();
currencyProp.put("type", "string");
currencyProp.put("description", "The currency of amount.");
properties.put("currency", currencyProp);
Map<String, Object> moneyJsonSchema = new HashMap<>();
moneyJsonSchema.put("type", "object");
moneyJsonSchema.put("properties", properties);
moneyJsonSchema.put("required", Arrays.asList("amount", "currency"));
CreateModelInteractionResponseFormat format =
CreateModelInteractionResponseFormat.of(
ResponseFormat.of(
TextResponseFormat.builder()
.mimeType(TextResponseFormatMimeType.APPLICATION_JSON)
.schema(moneyJsonSchema)
.build()));
CreateModelInteraction params =
CreateModelInteraction.builder()
.model(Model.of("gemini-3.8-flash"))
.input(InteractionsInput.of("What is the minimum hourly wage in Tokyo right now?"))
.tools(
Arrays.asList(
FileSearch.builder()
.fileSearchStoreNames(Arrays.asList("fileSearchStores/myfilesearchstore123"))
.build()))
.responseFormat(format)
.build();
Interaction interaction =
client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
System.out.println(interaction.outputText().orElse(""));
Go
package main
import (
"context"
"fmt"
"log"
"google.golang.org/genai"
"google.golang.org/genai/interactions/models/interactions"
"google.golang.org/genai/interactions/models/operations"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
moneyJsonSchema := map[string]any{
"type": "object",
"properties": map[string]any{
"amount": map[string]any{
"type": "string",
"description": "The numerical part of the amount.",
},
"currency": map[string]any{
"type": "string",
"description": "The currency of amount.",
},
},
"required": []string{"amount", "currency"},
}
format := interactions.NewCreateModelInteractionResponseFormat(
interactions.NewResponseFormat(interactions.TextResponseFormat{
MimeType: interactions.TextResponseFormatMimeTypeApplicationJSON.ToPointer(),
Schema: moneyJsonSchema,
}),
)
resp, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
Body: operations.NewCreateInteractionRequestBody(
interactions.CreateModelInteraction{
Model: interactions.Model("gemini-3.8-flash"),
Input: interactions.NewInteractionsInput("What is the minimum hourly wage in Tokyo right now?"),
Tools: []interactions.Tool{
interactions.NewTool(interactions.FileSearch{
FileSearchStoreNames: []string{"fileSearchStores/myfilesearchstore123"},
}),
},
ResponseFormat: &format,
},
),
})
if err != nil {
log.Fatal(err)
}
fmt.Println(resp.Interaction.GetOutputText())
}
REST
curl "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H 'Content-Type: application/json' \
-X POST \
-d '{
"model": "gemini-3.8-flash",
"input": "What is the minimum hourly wage in Tokyo right now?",
"tools": [{
"type": "file_search",
"file_search_store_names": ["$FILE_SEARCH_STORE_NAME"]
}],
"response_format": {
"type": "text",
"mime_type": "application/json",
"schema": {
"type": "object",
"properties": {
"amount": {"type": "string", "description": "The numerical part of the amount."},
"currency": {"type": "string", "description": "The currency of amount."}
},
"required": ["amount", "currency"]
}
}
}'
Obsługiwane modele
Wyszukiwanie plików obsługują te modele:
| Model | Wyszukiwanie plików |
|---|---|
| Gemini 4 Argon | ✔️ |
| Gemini 3.8 Flash | ✔️ |
| Gemini 3.6 Flash | ✔️ |
| Gemini 3.5 Flash-Lite | ✔️ |
| Gemini 3.1 Pro (wersja testowa) | ✔️ |
| Gemini 3.1 Flash-Lite | ✔️ |
| Gemini 3 Flash (wersja testowa) | ✔️ |
Obsługiwane kombinacje narzędzi
Modele Gemini 4 i Gemini 3 obsługują łączenie wbudowanych narzędzi (takich jak wyszukiwanie plików) z narzędziami niestandardowymi (wywoływanie funkcji). Więcej informacji znajdziesz na stronie Kombinacje narzędzi.
Obsługiwane typy plików
Wyszukiwanie plików obsługuje szeroką gamę formatów plików wymienionych w sekcjach poniżej.
Typy plików aplikacji
application/dartapplication/ecmascriptapplication/jsonapplication/ms-javaapplication/mswordapplication/pdfapplication/sqlapplication/typescriptapplication/vnd.curlapplication/vnd.dartapplication/vnd.ibm.secure-containerapplication/vnd.jupyterapplication/vnd.ms-excelapplication/vnd.oasis.opendocument.textapplication/vnd.openxmlformats-officedocument.presentationml.presentationapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheetapplication/vnd.openxmlformats-officedocument.wordprocessingml.documentapplication/vnd.openxmlformats-officedocument.wordprocessingml.templateapplication/x-cshapplication/x-hwpapplication/x-hwp-v5application/x-latexapplication/x-phpapplication/x-powershellapplication/x-shapplication/x-shellscriptapplication/x-texapplication/x-zshapplication/xmlapplication/zip
Typy plików tekstowych
text/1d-interleaved-parityfectext/REDtext/SGMLtext/cache-manifesttext/calendartext/cqltext/cql-extensiontext/cql-identifiertext/csstext/csvtext/csv-schematext/dnstext/encaprtptext/enrichedtext/exampletext/fhirpathtext/flexfectext/fwdredtext/gff3text/grammar-ref-listtext/hl7v2text/htmltext/javascripttext/jcr-cndtext/jsxtext/markdowntext/mizartext/n3text/parameterstext/parityfectext/phptext/plaintext/provenance-notationtext/prs.fallenstein.rsttext/prs.lines.tagtext/prs.prop.logictext/raptorfectext/rfc822-headerstext/rtftext/rtp-enc-aescm128text/rtploopbacktext/rtxtext/sgmltext/shaclctext/shextext/spdxtext/stringstext/t140text/tab-separated-valuestext/texmacstext/trofftext/tsvtext/tsxtext/turtletext/ulpfectext/uri-listtext/vcardtext/vnd.DMClientScripttext/vnd.IPTC.NITFtext/vnd.IPTC.NewsMLtext/vnd.atext/vnd.abctext/vnd.ascii-arttext/vnd.curltext/vnd.debian.copyrighttext/vnd.dvb.subtitletext/vnd.esmertec.theme-descriptortext/vnd.exchangeabletext/vnd.familysearch.gedcomtext/vnd.ficlab.flttext/vnd.flytext/vnd.fmi.flexstortext/vnd.gmltext/vnd.graphviztext/vnd.hanstext/vnd.hgltext/vnd.in3d.3dmltext/vnd.in3d.spottext/vnd.latex-ztext/vnd.motorola.reflextext/vnd.ms-mediapackagetext/vnd.net2phone.commcenter.commandtext/vnd.radisys.msml-basic-layouttext/vnd.senx.warpscripttext/vnd.sositext/vnd.sun.j2me.app-descriptortext/vnd.trolltech.linguisttext/vnd.wap.sitext/vnd.wap.sltext/vnd.wap.wmltext/vnd.wap.wmlscripttext/vtttext/wgsltext/x-asmtext/x-bibtextext/x-bootext/x-ctext/x-c++hdrtext/x-c++srctext/x-cassandratext/x-chdrtext/x-coffeescripttext/x-componenttext/x-cshtext/x-csharptext/x-csrctext/x-cudatext/x-dtext/x-difftext/x-dsrctext/x-emacs-lisptext/x-erlangtext/x-gff3text/x-gotext/x-haskelltext/x-javatext/x-java-propertiestext/x-java-sourcetext/x-kotlintext/x-lilypondtext/x-lisptext/x-literate-haskelltext/x-luatext/x-moctext/x-objcsrctext/x-pascaltext/x-pcs-gcdtext/x-perltext/x-perl-scripttext/x-pythontext/x-python-scripttext/x-r-markdowntext/x-rsrctext/x-rsttext/x-ruby-scripttext/x-rusttext/x-sasstext/x-scalatext/x-schemetext/x-script.pythontext/x-scsstext/x-setexttext/x-sfvtext/x-shtext/x-siestatext/x-sostext/x-sqltext/x-swifttext/x-tcltext/x-textext/x-vbasictext/x-vcalendartext/xmltext/xml-dtdtext/xml-external-parsed-entitytext/yaml
Ograniczenia
- Live API: wyszukiwanie plików nie jest obsługiwane w Live API.
- Niezgodność narzędzi: wbudowanych narzędzi do powiązania ze źródłami informacji nie można ze sobą łączyć. Na przykład w tym samym żądaniu nie można używać wyszukiwania plików jednocześnie z powiązaniem ze źródłami informacji przy użyciu wyszukiwarki Google ani z kontekstem adresu URL.
Ograniczenia liczby żądań
Aby zapewnić stabilność usługi, interfejs File Search API ma te limity:
- Maksymalny rozmiar pliku / limit na dokument: 100 MB
- Łączny rozmiar magazynów wyszukiwania plików w projekcie (na podstawie poziomu użytkownika):
- Bezpłatnie: 1 GB
- Poziom 1: 10 GB
- Poziom 2: 100 GB
- Poziom 3: 1 TB
- Zalecenie: aby zapewnić optymalne opóźnienia pobierania, ogranicz rozmiar każdego magazynu wyszukiwania plików do mniej niż 20 GB.
Ceny
- Opłaty za wektoryzację są naliczane w momencie indeksowania na podstawie obowiązującego cennika wektorów.
- Przechowywanie jest bezpłatne.
- Wektory dystrybucyjne czasu zapytania są bezpłatne.
- Pobrane tokeny dokumentów są rozliczane jako zwykłe tokeny kontekstu.
Co dalej?
- Zapoznaj się z dokumentacją interfejsu API File Search Stores i File Search Documents.