Skip to main content

Tech Stack

The AI Ingredient Scanner leverages modern AI and cloud technologies to deliver reliable ingredient analysis.

Architecture Diagramโ€‹

Technology Stackโ€‹

Core AIโ€‹

TechnologyPurposeDetails
Google Gemini 2.0 FlashLLMAnalysis, validation, translation
LangGraphOrchestrationMulti-agent workflow management
LangSmithTracingLLM call logging and debugging

Backendโ€‹

TechnologyPurposeDetails
Python 3.11+LanguageType hints, async support
FastAPIREST APIMobile app integration
StreamlitWeb UIInteractive dashboard
PydanticValidationRequest/response schemas

Data Layerโ€‹

TechnologyPurposeDetails
Qdrant CloudVector DBSemantic ingredient search
Redis CloudCachingSession persistence
Google EmbeddingsVectorsgemini-embedding-001 model

Mobileโ€‹

TechnologyPurposeDetails
React NativeFrameworkCross-platform mobile
ExpoToolchainDevelopment and builds
TypeScriptLanguageType-safe mobile code
expo-cameraCameraNative camera access

LLM Integrationโ€‹

Gemini 2.0 Flashโ€‹

Used for all AI capabilities:

# Analysis generation
client.models.generate_content(
model="gemini-2.0-flash",
contents=analysis_prompt,
)

# Vision OCR with translation
client.models.generate_content(
model="gemini-2.0-flash",
contents=[image_part, ocr_prompt],
)

# Google Search grounding
config = types.GenerateContentConfig(
tools=[types.Tool(google_search=types.GoogleSearch())]
)

Model Selection Rationaleโ€‹

ModelUse CaseWhy
gemini-2.0-flashAll operationsFast, capable, cost-effective
gemini-embedding-001Vector searchHigh-quality embeddings

Vector Databaseโ€‹

Qdrant Configurationโ€‹

COLLECTION_NAME = "ingredients"
VECTOR_SIZE = 768 # gemini-embedding-001 output
DISTANCE = Distance.COSINE

# Query
results = client.query_points(
collection_name=COLLECTION_NAME,
query=embedding,
limit=1,
)

Payload Schemaโ€‹

{
"name": "Glycerin",
"purpose": "Humectant, moisturizer",
"safety_rating": 9,
"concerns": "No known concerns",
"recommendation": "SAFE",
"allergy_risk_flag": "low",
"origin": "Natural",
"category": "Both",
"regulatory_status": "FDA approved, EU compliant"
}

API Communicationโ€‹

Environment Configurationโ€‹

# Required
GOOGLE_API_KEY= # Gemini API access
QDRANT_URL= # Vector database
QDRANT_API_KEY= # Qdrant authentication

# Optional
REDIS_URL= # Session caching
LANGCHAIN_API_KEY= # LangSmith tracing

Deployment Optionsโ€‹

EnvironmentStack
Local DevelopmentStreamlit + uvicorn
Production APIGoogle Cloud Run
Mobile TestingExpo Go
Production MobileEAS Build

Performance Optimizationโ€‹

Caching Strategyโ€‹

  • Qdrant: Ingredient data persisted permanently
  • Redis: Session state cached for 24 hours
  • LRU Cache: In-memory settings caching

Parallel Processingโ€‹

# Research agent processes 3 ingredients per worker
BATCH_SIZE = 3

with ThreadPoolExecutor(max_workers=num_workers) as executor:
futures = {
executor.submit(_research_batch, idx, batch): idx
for idx, batch in enumerate(batches)
}