Skip to main content 首页 创作者 ovachiever droid-tings google-gemini-file-search
google-gemini-file-search Build document Q&A and searchable knowledge bases with Google Gemini File Search - fully managed RAG with automatic chunking, embeddings, and citations. Upload 100+ file formats (PDF, Word, Excel, code), configure semantic search, and query with natural language.
Use when: building document Q&A systems, creating searchable knowledge bases, implementing semantic search without managing embeddings, indexing large document collections (100+ formats), or troubleshooting document immutability errors (delete+re-upload required), storage quota issues (3x input size for embeddings), chunking configuration (500 tokens/chunk recommended), metadata limits (20 key-value pairs max), indexing cost surprises ($0.15/1M tokens one-time), operation polling timeouts (wait for done: true), force delete errors, or model compatibility (Gemini 2.5 Pro/Flash only).
跳到安装 Skills Marketplace 发现并探索由社区构建的 Agent Skills
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/ovachiever/droid-tings --skill google-gemini-file-search命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
下载 Zip 下载中... Build backend AI with Vercel AI SDK v5/v6. Covers v6 beta (Agent abstraction, tool approval, reranking),
v4→v5 migration (breaking changes), latest models (GPT-5/5.1, Claude 4.x, Gemini 2.5), Workers startup
fix, and 12 error solutions (AI_APICallError, AI_NoObjectGeneratedError, streamText silent errors).
Use when: implementing AI SDK v5/v6, migrating v4→v5, troubleshooting errors, fixing Workers startup
issues, or updating to latest models.
Build React chat interfaces with Vercel AI SDK v5/v6. Covers v6 beta (agent integration, tool approval,
auto-submit), v4→v5 migration (breaking changes), useChat/useCompletion/useObject/useAssistant hooks,
and 12 UI error solutions (stream parsing, stale body values, React update depth).
Use when: implementing AI SDK v5/v6 chat UIs, migrating v4→v5, troubleshooting "useChat failed to parse
stream", "useChat no response", or "stale body values" errors, or integrating OpenAI assistants.
name google-gemini-file-search description Build document Q&A and searchable knowledge bases with Google Gemini File Search - fully managed RAG with automatic chunking, embeddings, and citations. Upload 100+ file formats (PDF, Word, Excel, code), configure semantic search, and query with natural language.
Use when: building document Q&A systems, creating searchable knowledge bases, implementing semantic search without managing embeddings, indexing large document collections (100+ formats), or troubleshooting document immutability errors (delete+re-upload required), storage quota issues (3x input size for embeddings), chunking configuration (500 tokens/chunk recommended), metadata limits (20 key-value pairs max), indexing cost surprises ($0.15/1M tokens one-time), operation polling timeouts (wait for done: true), force delete errors, or model compatibility (Gemini 2.5 Pro/Flash only).
license MIT allowed-tools ["Bash","Read","Write","Glob","Grep","WebFetch"] metadata {"version":"1.0.0","last_verified":"2025-11-10","package_versions":{"@google/genai":"^0.21.0"},"supported_models":["gemini-2.5-pro","gemini-2.5-flash"],"node_version":">=18.0.0","token_savings":"~65%","errors_prevented":8,"keywords":["file search","gemini rag","document search","knowledge base","semantic search","google embeddings","file upload","managed rag","automatic citations","document qa","retrieval augmented generation","vector search","grounding","file indexing"]}
Google Gemini File Search Setup
Overview
Google Gemini File Search is a fully managed RAG (Retrieval-Augmented Generation) system that eliminates the need for separate vector databases, custom chunking logic, or embedding generation code. Upload documents (PDFs, Word, Excel, code files, etc.) and query them using natural language—Gemini automatically handles intelligent chunking, embedding with its optimized model, semantic search, and citation generation.
What This Skill Provides:
Complete setup guide for @google/genai File Search API
TypeScript/JavaScript SDK configuration patterns
Working templates for 3 deployment scenarios (Node.js, Cloudflare Workers, Next.js)
8 documented common errors with prevention strategies
Chunking best practices for optimal retrieval
Cost optimization techniques
Comparison guide (vs Cloudflare Vectorize, OpenAI Files API, Claude MCP)
Key Features of File Search:
100+ File Formats : PDF, Word (.docx), Excel (.xlsx), PowerPoint (.pptx), Markdown, JSON, CSV, code files (Python, JavaScript, TypeScript, Java, C++, Go, Rust, etc.)
Automatic Embeddings : Uses Google's Gemini Embedding model (no custom embedding code required)
Semantic Search : Vector-based search understands meaning and context, not just keywords
Built-in Citations : Grounding metadata automatically points to specific document sections
Custom Metadata : Filter queries by up to 20 custom key-value pairs per document
Configurable Chunking : Control chunk size (tokens) and overlap for precision tuning
Cost-Effective : $0.15/1M tokens for one-time indexing, free storage (up to limits), free query-time embeddings
When to Use This Skill
Ideal Use Cases:
Building customer support knowledge bases (manuals, FAQs, troubleshooting guides)
Creating internal documentation search (company wikis, policies, procedures)
Legal/compliance document analysis (contracts, regulations, case law)
Research tools (academic papers, articles, textbooks)
Code documentation search (API docs, SDK references, examples)
Product information retrieval (specs, datasheets, user guides)
Use File Search When:
✅ You want a fully managed RAG solution (no vector DB setup)
✅ Cost predictability matters (pay-per-indexing, not continuous storage fees)
✅ You need broad file format support (100+ types out of the box)
✅ Citations are important (built-in grounding metadata)
✅ Simple deployment is priority (single API setup)
✅ Documents are relatively static (updates are infrequent) Use Cloudflare Vectorize/AutoRAG Instead When:
✅ Global edge performance is critical (low-latency worldwide)
✅ Building full-stack apps on Cloudflare (Workers, R2, D1)
✅ You need custom embedding models or retrieval logic
✅ Real-time data updates from R2 or external sources
Use OpenAI Files API Instead When:
✅ Already using OpenAI Assistants API (conversational threads)
✅ Need to attach knowledge to persistent assistant threads
✅ Working with very large file collections (10,000+ files per store)
✅ Prefer storage-based pricing model ($0.10/GB/day)
When NOT to Use This Skill
❌ Need custom embedding models (File Search locks you to Gemini Embeddings)
❌ Documents update frequently (no streaming updates, must delete+re-upload)
❌ Building conversational AI agents (use OpenAI Assistants or Claude MCP instead)
❌ Need BM25/hybrid search (File Search is vector-only)
❌ Require advanced reranking configuration (automatic only)
❌ Need to parse images/tables from PDFs (text extraction only)
Prerequisites
1. Google AI API Key
1 GB storage (total across all file search stores)
1,500 requests per day
1 million tokens per minute
Indexing: $0.15 per 1M input tokens (one-time)
Storage: Free (Tier 1: 10 GB, Tier 2: 100 GB, Tier 3: 1 TB)
Query-time embeddings: Free (retrieved context counts as input tokens)
2. Node.js Environment Minimum Version: Node.js 18+ (v20+ recommended)
3. Install @google/genai SDK npm install @google/genai
pnpm add @google/genai
yarn add @google/genai
Current Stable Version: 0.21.0+ (verify with npm view @google/genai version)
4. TypeScript Configuration (Optional but Recommended) {
"compilerOptions" : {
"target" : "ES2020" ,
"module" : "ESNext" ,
"moduleResolution" : "node" ,
"esModuleInterop" : true ,
"strict" : true ,
"skipLibCheck" : true
}
}
Common Errors Prevented This skill prevents 8 common errors encountered when implementing File Search:
Error 1: Document Immutability Error: Documents cannot be modified after indexing
Cause: Documents are immutable once indexed. There is no PATCH or UPDATE operation.
Prevention:
Use the delete+re-upload pattern for updates:
await ai.fileSearchStores .documents .update ({
name : documentName,
customMetadata : { version : '2.0' }
})
const docs = await ai.fileSearchStores .documents .list ({
parent : fileStore.name
})
const oldDoc = docs.documents .find (d => d.displayName === 'manual.pdf' )
if (oldDoc) {
await ai.fileSearchStores .documents .delete ({
name : oldDoc.name ,
force : true
})
}
await ai.fileSearchStores .uploadToFileSearchStore ({
name : fileStore.name ,
file : fs.createReadStream ('manual-v2.pdf' ),
config : { displayName : 'manual.pdf' }
})
Error 2: Storage Quota Exceeded Error: Quota exceeded. Expected 1GB limit, but 3.2GB used.
Cause: Storage calculation includes input files + embeddings + metadata. Total storage ≈ 3x input size.
Prevention:
Calculate storage before upload:
const fileSize = fs.statSync ('data.pdf' ).size
const fileSize = fs.statSync ('data.pdf' ).size
const estimatedStorage = fileSize * 3
console .log (`Estimated storage: ${estimatedStorage / 1e9 } GB` )
if (estimatedStorage > 1e9 ) {
console .warn ('⚠️ File may exceed free tier 1 GB limit' )
}
Error 3: Incorrect Chunking Configuration Symptom:
Poor retrieval quality, irrelevant results, or context cutoff mid-sentence.
Cause: Default chunking may not be optimal for your content type.
Prevention:
Use recommended chunking strategy:
await ai.fileSearchStores .uploadToFileSearchStore ({
name : fileStore.name ,
file : fs.createReadStream ('docs.pdf' )
})
await ai.fileSearchStores .uploadToFileSearchStore ({
name : fileStore.name ,
file : fs.createReadStream ('docs.pdf' ),
config : {
chunkingConfig : {
whiteSpaceConfig : {
maxTokensPerChunk : 500 ,
maxOverlapTokens : 50
}
}
}
})
Technical docs/code: 500 tokens/chunk, 50 overlap
Prose/articles: 800 tokens/chunk, 80 overlap
Legal/contracts: 300 tokens/chunk, 30 overlap (high precision)
Error 4: Metadata Limits Exceeded Error: Maximum 20 custom metadata key-value pairs allowed
Cause: Each document can have at most 20 metadata fields.
Prevention:
Design compact metadata schema:
await ai.fileSearchStores .uploadToFileSearchStore ({
name : fileStore.name ,
file : fs.createReadStream ('doc.pdf' ),
config : {
customMetadata : {
doc_type : 'manual' ,
version : '1.0' ,
author : 'John Doe' ,
department : 'Engineering' ,
created_date : '2025-01-01' ,
}
}
})
await ai.fileSearchStores .uploadToFileSearchStore ({
name : fileStore.name ,
file : fs.createReadStream ('doc.pdf' ),
config : {
customMetadata : {
doc_type : 'manual' ,
version : '1.0' ,
author_dept : 'John Doe|Engineering' ,
dates : JSON .stringify ({
created : '2025-01-01' ,
updated : '2025-01-15'
})
}
}
})
Error 5: Indexing Cost Surprises Symptom:
Unexpected bill for $375 after uploading 10 GB of documents.
Cause: Indexing costs are one-time but calculated per input token ($0.15/1M tokens).
Prevention:
Estimate costs before indexing:
await uploadAllDocuments (fileStore.name , './data' )
const totalSize = getTotalDirectorySize ('./data' )
const estimatedTokens = (totalSize / 4 )
const indexingCost = (estimatedTokens / 1e6 ) * 0.15
console .log (`Estimated indexing cost: $${indexingCost.toFixed(2 )} ` )
console .log (`Estimated storage: ${(totalSize * 3 ) / 1e9 } GB` )
const proceed = await confirm (`Proceed with indexing? Cost: $${indexingCost.toFixed(2 )} ` )
if (proceed) {
await uploadAllDocuments (fileStore.name , './data' )
}
1 GB text ≈ 250M tokens = $37.50 indexing
100 MB PDF ≈ 25M tokens = $3.75 indexing
10 MB code ≈ 2.5M tokens = $0.38 indexing
Error 6: Not Polling Operation Status Symptom:
Query returns no results immediately after upload, or incomplete indexing.
Cause: File uploads are processed asynchronously. Must poll operation until done: true.
Prevention:
Always poll operation status:
const operation = await ai.fileSearchStores .uploadToFileSearchStore ({
name : fileStore.name ,
file : fs.createReadStream ('large.pdf' )
})
const operation = await ai.fileSearchStores .uploadToFileSearchStore ({
name : fileStore.name ,
file : fs.createReadStream ('large.pdf' )
})
while (!operation.done ) {
await new Promise (resolve => setTimeout (resolve, 1000 ))
operation = await ai.operations .get ({ name : operation.name })
console .log (`Indexing progress: ${operation.metadata?.progress || 'processing...' } ` )
}
if (operation.error ) {
throw new Error (`Indexing failed: ${operation.error.message} ` )
}
console .log ('✅ Indexing complete:' , operation.response .displayName )
Error 7: Forgetting Force Delete Error: Cannot delete store with documents. Set force=true.
Cause: Stores with documents require force: true to delete (prevents accidental deletion).
Prevention:
Always use force: true when deleting non-empty stores:
await ai.fileSearchStores .delete ({
name : fileStore.name
})
await ai.fileSearchStores .delete ({
name : fileStore.name ,
force : true
})
const docs = await ai.fileSearchStores .documents .list ({ parent : fileStore.name })
for (const doc of docs.documents || []) {
await ai.fileSearchStores .documents .delete ({
name : doc.name ,
force : true
})
}
await ai.fileSearchStores .delete ({ name : fileStore.name })
Error 8: Using Unsupported Models Error: File Search is only supported for Gemini 2.5 Pro and Flash models
Cause: File Search requires Gemini 2.5 Pro or Gemini 2.5 Flash. Gemini 1.5 models are not supported.
Prevention:
Always use 2.5 models:
const response = await ai.models .generateContent ({
model : 'gemini-1.5-pro' ,
contents : 'What is the installation procedure?' ,
config : {
tools : [{
fileSearch : { fileSearchStoreNames : [fileStore.name ] }
}]
}
})
const response = await ai.models .generateContent ({
model : 'gemini-2.5-flash' ,
contents : 'What is the installation procedure?' ,
config : {
tools : [{
fileSearch : { fileSearchStoreNames : [fileStore.name ] }
}]
}
})
Setup Instructions
Step 1: Initialize Client import { GoogleGenAI } from '@google/genai'
import fs from 'fs'
const ai = new GoogleGenAI ({
apiKey : process.env .GOOGLE_API_KEY
})
if (!process.env .GOOGLE_API_KEY ) {
throw new Error ('GOOGLE_API_KEY environment variable is required' )
}
Step 2: Create File Search Store
const fileStore = await ai.fileSearchStores .create ({
config : {
displayName : 'my-knowledge-base' ,
customMetadata : {
project : 'customer-support' ,
environment : 'production'
}
}
})
console .log ('Created store:' , fileStore.name )
const stores = await ai.fileSearchStores .list ({
pageSize : 20
})
let targetStore = null
let pageToken = null
do {
const page = await ai.fileSearchStores .list ({ pageToken })
targetStore = page.fileSearchStores .find (
s => s.displayName === 'my-knowledge-base'
)
pageToken = page.nextPageToken
} while (!targetStore && pageToken)
if (targetStore) {
console .log ('Found existing store:' , targetStore.name )
} else {
console .log ('Store not found, creating new one...' )
}
Step 3: Upload Documents const operation = await ai.fileSearchStores .uploadToFileSearchStore ({
name : fileStore.name ,
file : fs.createReadStream ('./docs/manual.pdf' ),
config : {
displayName : 'Installation Manual' ,
customMetadata : {
doc_type : 'manual' ,
version : '1.0' ,
language : 'en'
},
chunkingConfig : {
whiteSpaceConfig : {
maxTokensPerChunk : 500 ,
maxOverlapTokens : 50
}
}
}
})
while (!operation.done ) {
await new Promise (resolve => setTimeout (resolve, 1000 ))
operation = await ai.operations .get ({ name : operation.name })
}
console .log ('✅ Indexed:' , operation.response .displayName )
Batch Upload (Concurrent):
const filePaths = [
'./docs/manual.pdf' ,
'./docs/faq.md' ,
'./docs/troubleshooting.docx'
]
const uploadPromises = filePaths.map (filePath =>
ai.fileSearchStores .uploadToFileSearchStore ({
name : fileStore.name ,
file : fs.createReadStream (filePath),
config : {
displayName : filePath.split ('/' ).pop (),
customMetadata : {
doc_type : 'support' ,
source_path : filePath
},
chunkingConfig : {
whiteSpaceConfig : {
maxTokensPerChunk : 500 ,
maxOverlapTokens : 50
}
}
}
})
)
const operations = await Promise .all (uploadPromises)
for (const operation of operations) {
let op = operation
while (!op.done ) {
await new Promise (resolve => setTimeout (resolve, 1000 ))
op = await ai.operations .get ({ name : op.name })
}
console .log ('✅ Indexed:' , op.response .displayName )
}
Step 4: Query with File Search const response = await ai.models .generateContent ({
model : 'gemini-2.5-flash' ,
contents : 'What are the safety precautions for installation?' ,
config : {
tools : [{
fileSearch : {
fileSearchStoreNames : [fileStore.name ]
}
}]
}
})
console .log ('Answer:' , response.text )
const grounding = response.candidates [0 ].groundingMetadata
if (grounding?.groundingChunks ) {
console .log ('\nSources:' )
grounding.groundingChunks .forEach ((chunk, i ) => {
console .log (`${i + 1 } . ${chunk.retrievedContext?.title || 'Unknown' } ` )
console .log (` URI: ${chunk.retrievedContext?.uri || 'N/A' } ` )
})
}
Query with Metadata Filtering:
const response = await ai.models .generateContent ({
model : 'gemini-2.5-flash' ,
contents : 'How do I reset the device?' ,
config : {
tools : [{
fileSearch : {
fileSearchStoreNames : [fileStore.name ],
metadataFilter : 'doc_type="troubleshooting" AND language="en" AND version="1.0"'
}
}]
}
})
console .log ('Answer:' , response.text )
AND: key1="value1" AND key2="value2"
OR: key1="value1" OR key1="value2"
Parentheses: (key1="a" OR key1="b") AND key2="c"
Step 5: List and Manage Documents
const docs = await ai.fileSearchStores .documents .list ({
parent : fileStore.name ,
pageSize : 20
})
console .log (`Total documents: ${docs.documents?.length || 0 } ` )
docs.documents ?.forEach (doc => {
console .log (`- ${doc.displayName} (${doc.name} )` )
console .log (` Metadata:` , doc.customMetadata )
})
const docDetails = await ai.fileSearchStores .documents .get ({
name : docs.documents [0 ].name
})
console .log ('Document details:' , docDetails)
await ai.fileSearchStores .documents .delete ({
name : docs.documents [0 ].name ,
force : true
})
Step 6: Cleanup
await ai.fileSearchStores .delete ({
name : fileStore.name ,
force : true
})
console .log ('✅ Store deleted' )
Recommended Chunking Strategies Chunking configuration significantly impacts retrieval quality. Adjust based on content type:
Technical Documentation chunkingConfig : {
whiteSpaceConfig : {
maxTokensPerChunk : 500 ,
maxOverlapTokens : 50
}
}
Best for: API docs, SDK references, code examples, configuration guides
Prose and Articles chunkingConfig : {
whiteSpaceConfig : {
maxTokensPerChunk : 800 ,
maxOverlapTokens : 80
}
}
Best for: Blog posts, news articles, product descriptions, marketing materials
Legal and Contracts chunkingConfig : {
whiteSpaceConfig : {
maxTokensPerChunk : 300 ,
maxOverlapTokens : 30
}
}
Best for: Legal documents, contracts, regulations, compliance docs
FAQ and Support chunkingConfig : {
whiteSpaceConfig : {
maxTokensPerChunk : 400 ,
maxOverlapTokens : 40
}
}
Best for: FAQs, troubleshooting guides, how-to articles
General Rule: Maintain 10% overlap (overlap = chunk size / 10) to prevent context loss at chunk boundaries.
Metadata Best Practices Design metadata schema for filtering and organization:
Example: Customer Support Knowledge Base customMetadata : {
doc_type : 'faq' | 'manual' | 'troubleshooting' | 'guide' ,
product : 'widget-pro' | 'widget-lite' ,
version : '1.0' | '2.0' ,
language : 'en' | 'es' | 'fr' ,
category : 'installation' | 'configuration' | 'maintenance' ,
priority : 'critical' | 'normal' | 'low' ,
last_updated : '2025-01-15' ,
author : 'support-team'
}
metadataFilter : 'product="widget-pro" AND (doc_type="troubleshooting" OR doc_type="faq") AND language="en"'
Example: Legal Document Repository customMetadata : {
doc_type : 'contract' | 'regulation' | 'case-law' | 'policy' ,
jurisdiction : 'US' | 'EU' | 'UK' ,
practice_area : 'employment' | 'corporate' | 'ip' | 'tax' ,
effective_date : '2025-01-01' ,
status : 'active' | 'archived' ,
confidentiality : 'public' | 'internal' | 'privileged'
}
Example: Code Documentation customMetadata : {
doc_type : 'api-reference' | 'tutorial' | 'example' | 'changelog' ,
language : 'javascript' | 'python' | 'java' | 'go' ,
framework : 'react' | 'nextjs' | 'express' | 'fastapi' ,
version : '1.2.0' ,
difficulty : 'beginner' | 'intermediate' | 'advanced'
}
Use consistent key naming (snake_case or camelCase)
Limit to most important filterable fields (20 max)
Use enums/constants for values (easier filtering)
Include version and date fields for time-based filtering
Cost Optimization
1. Deduplicate Before Upload
const uploadedHashes = new Set <string >()
async function uploadWithDeduplication (filePath : string ) {
const fileHash = await getFileHash (filePath)
if (uploadedHashes.has (fileHash)) {
console .log (`Skipping duplicate: ${filePath} ` )
return
}
await ai.fileSearchStores .uploadToFileSearchStore ({
name : fileStore.name ,
file : fs.createReadStream (filePath)
})
uploadedHashes.add (fileHash)
}
2. Compress Large Files
3. Use Metadata Filtering to Reduce Query Scope
const response = await ai.models .generateContent ({
model : 'gemini-2.5-flash' ,
contents : 'Reset procedure?' ,
config : {
tools : [{ fileSearch : { fileSearchStoreNames : [fileStore.name ] } }]
}
})
const response = await ai.models .generateContent ({
model : 'gemini-2.5-flash' ,
contents : 'Reset procedure?' ,
config : {
tools : [{
fileSearch : {
fileSearchStoreNames : [fileStore.name ],
metadataFilter : 'doc_type="troubleshooting"'
}
}]
}
})
4. Choose Flash Over Pro for Cost Savings
model : 'gemini-2.5-flash'
model : 'gemini-2.5-pro'
5. Monitor Storage Usage
const stores = await ai.fileSearchStores .list ()
for (const store of stores.fileSearchStores || []) {
const docs = await ai.fileSearchStores .documents .list ({
parent : store.name
})
console .log (`Store: ${store.displayName} ` )
console .log (`Documents: ${docs.documents?.length || 0 } ` )
console .log (`Estimated storage: ~${(docs.documents?.length || 0 ) * 10 } MB` )
}
Testing & Verification
Verify Store Creation const store = await ai.fileSearchStores .get ({
name : fileStore.name
})
console .assert (store.displayName === 'my-knowledge-base' , 'Store name mismatch' )
console .log ('✅ Store created successfully' )
Verify Document Indexing const docs = await ai.fileSearchStores .documents .list ({
parent : fileStore.name
})
console .assert (docs.documents ?.length > 0 , 'No documents indexed' )
console .log (`✅ ${docs.documents?.length} documents indexed` )
Verify Query Functionality const response = await ai.models .generateContent ({
model : 'gemini-2.5-flash' ,
contents : 'What is this knowledge base about?' ,
config : {
tools : [{ fileSearch : { fileSearchStoreNames : [fileStore.name ] } }]
}
})
console .assert (response.text .length > 0 , 'Empty response' )
console .log ('✅ Query successful:' , response.text .substring (0 , 100 ) + '...' )
Verify Citations const response = await ai.models .generateContent ({
model : 'gemini-2.5-flash' ,
contents : 'Provide a specific answer with citations.' ,
config : {
tools : [{ fileSearch : { fileSearchStoreNames : [fileStore.name ] } }]
}
})
const grounding = response.candidates [0 ].groundingMetadata
console .assert (
grounding?.groundingChunks ?.length > 0 ,
'No grounding/citations returned'
)
console .log (`✅ ${grounding?.groundingChunks?.length} citations returned` )
Integration Examples This skill includes 3 working templates in the templates/ directory:
Template 1: basic-node-rag Minimal Node.js/TypeScript example demonstrating:
Create file search store
Upload multiple documents
Query with natural language
Display citations
Use when: Learning File Search, prototyping, simple CLI tools
cd templates/basic-node-rag
npm install
npm run dev
Template 2: cloudflare-worker-rag Cloudflare Workers integration showing:
Edge API for document upload
Edge API for semantic search
Integration with R2 for document storage
Hybrid architecture (Gemini File Search + Cloudflare edge)
Use when: Building global edge applications, integrating with Cloudflare stack
cd templates/cloudflare-worker-rag
npm install
npx wrangler deploy
Template 3: nextjs-docs-search Full-stack Next.js application featuring:
Document upload UI with drag-and-drop
Real-time search interface
Citation rendering with source links
Metadata filtering UI
Use when: Building production documentation sites, knowledge bases
cd templates/nextjs-docs-search
npm install
npm run dev
Comparison: File Search vs Alternatives Feature Gemini File Search Cloudflare Vectorize OpenAI Files API Setup Complexity Simple (single API) Moderate (DIY RAG) Simple (single API) File Format Support 100+ types Manual (text/embeddings) 20+ types Max File Size 100 MB N/A 512 MB Max Files/Store Unknown Unlimited 10,000 Custom Embeddings No (Gemini only) Yes (any model) No (OpenAI only) Chunking Control Limited (token-based) Full control None Global Distribution No (US-centric) Yes (edge network) No Citations Yes (automatic) Manual implementation Yes (automatic) Metadata Filtering Yes (20 fields) Yes (unlimited) Yes Streaming Updates No (delete+re-upload) Yes (AutoRAG) No Pricing Model Pay-per-index Usage-based Storage-based Free Tier 1 GB storage Developer tier 1 GB storage TypeScript SDK Full support Full support Full support
Cost Comparison (10 GB Knowledge Base, 1 Year):
Indexing: 10GB ≈ 2.5B tokens × $0.15/1M = $375 one-time
Storage: Free (Tier 1 covers 10 GB)
Queries: Standard pricing
Total Year 1: $375
Indexing: Free
Storage: 10GB × $0.10/GB/day = $365/year
Queries: Standard pricing
Total Year 1: $365
Cloudflare Vectorize (DIY):
Indexing: Workers AI embeddings (varies)
Storage: Vectorize pricing
Queries: Workers AI pricing
Total Year 1: ~$100-500 (depends on usage)
Winner: OpenAI for year 1, Gemini for year 2+ (if low update frequency)
Troubleshooting
Issue: "API key not valid" Cause: Invalid or missing API key
echo $GOOGLE_API_KEY
export GOOGLE_API_KEY="your-api-key-here"
echo "GOOGLE_API_KEY=your-api-key-here" >> .env
Issue: "Quota exceeded" Cause: Exceeded free tier limits (1 GB storage or 1,500 requests/day)
Delete old stores: ai.fileSearchStores.delete({ name, force: true })
Upgrade to paid tier: https://ai.google.dev/pricing
Wait until quota resets (daily at midnight UTC)
Issue: "File format not supported" Cause: Uploaded file type is not in the 100+ supported formats
Issue: "No results returned" Cause: Documents not fully indexed, or query too vague
Verify indexing complete: Poll operation until done: true
Check document count: ai.fileSearchStores.documents.list()
Refine query: Be more specific
Adjust metadata filter: May be too restrictive
Issue: "Poor retrieval quality" Cause: Suboptimal chunking configuration
Reduce maxTokensPerChunk for more precise retrieval (try 300-500)
Increase overlap to 10-15% of chunk size
Re-upload documents with new chunking config
References Bundled Resources in This Skill:
references/api-reference.md - Complete API documentation
references/chunking-best-practices.md - Detailed chunking strategies
references/pricing-calculator.md - Cost estimation guide
references/migration-from-openai.md - Migration guide from OpenAI Files API
scripts/create-store.ts - CLI tool to create stores
scripts/upload-batch.ts - Batch upload script
scripts/query-store.ts - Interactive query tool
scripts/cleanup.ts - Cleanup script
templates/basic-node-rag/ - Minimal Node.js example
templates/cloudflare-worker-rag/ - Edge deployment example
templates/nextjs-docs-search/ - Full-stack Next.js app
Skill Version: 1.0.0
Last Verified: 2025-11-10
Package Version: @google/genai ^0.21.0
Token Savings: ~65%
Errors Prevented: 8