{"id":34574358,"url":"https://github.com/eiberham/food-tracker-api","last_synced_at":"2026-05-06T13:10:25.041Z","repository":{"id":326795081,"uuid":"1105673445","full_name":"eiberham/food-tracker-api","owner":"eiberham","description":":robot: AI-powered food tracker api built with FastAPI, Langchain agent, Langgraph Workflows, and Supabase for vector search and RAG.","archived":false,"fork":false,"pushed_at":"2026-01-26T02:39:31.000Z","size":555,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-26T17:51:52.945Z","etag":null,"topics":["agentic-ai","fastapi","langchain","pydantic","sqlalchemy","supabase","terraform"],"latest_commit_sha":null,"homepage":"https://fastapi-api-hxw4qx7g2q-uc.a.run.app/docs","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eiberham.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-28T01:42:55.000Z","updated_at":"2026-01-26T02:39:34.000Z","dependencies_parsed_at":"2026-01-01T12:01:29.689Z","dependency_job_id":null,"html_url":"https://github.com/eiberham/food-tracker-api","commit_stats":null,"previous_names":["eiberham/food-tracker-api"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/eiberham/food-tracker-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eiberham%2Ffood-tracker-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eiberham%2Ffood-tracker-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eiberham%2Ffood-tracker-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eiberham%2Ffood-tracker-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eiberham","download_url":"https://codeload.github.com/eiberham/food-tracker-api/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eiberham%2Ffood-tracker-api/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32695059,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-06T08:33:17.875Z","status":"ssl_error","status_checked_at":"2026-05-06T08:33:17.221Z","response_time":117,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agentic-ai","fastapi","langchain","pydantic","sqlalchemy","supabase","terraform"],"created_at":"2025-12-24T09:48:04.018Z","updated_at":"2026-05-06T13:10:25.036Z","avatar_url":"https://github.com/eiberham.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Food Tracker\n\n\u003ctable border=\"0\" cellspacing=\"0\" cellpadding=\"0\" style=\"border-collapse: collapse; border: none;\"\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003cimg alt=\"GitHub\" src=\"https://img.shields.io/github/license/eiberham/food-tracker-api?style=for-the-badge\"\u003e\u003c/td\u003e\n    \u003ctd\u003e\u003cimg alt=\"GitHub code size in bytes\" src=\"https://img.shields.io/github/languages/code-size/eiberham/food-tracker-api?style=for-the-badge\"\u003e\u003c/td\u003e\n    \u003ctd\u003e\u003cimg alt=\"GitHub top language\" src=\"https://img.shields.io/github/languages/top/eiberham/food-tracker-api?style=for-the-badge\"\u003e\u003c/td\u003e\n    \u003ctd\u003e\u003cimg alt=\"GitHub last commit\" src=\"https://img.shields.io/github/last-commit/eiberham/food-tracker-api?style=for-the-badge\"\u003e\u003c/td\u003e\n    \u003ctd\u003e\u003cimg alt=\"GitHub stars\" src=\"https://img.shields.io/github/stars/eiberham/food-tracker-api?style=for-the-badge\"\u003e\u003c/td\u003e\n    \u003ctd\u003e\u003cimg alt=\"GitHub workflow status\" src=\"https://img.shields.io/github/actions/workflow/status/eiberham/food-tracker-api/ci.yml?style=for-the-badge\"\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nThis is a FastAPI backend that combines LangChain Agents, Supabase, and pgvector to deliver an AI-powered food tracking system. The API supports natural-language queries, vector search, and tool calling agents to retrieve meals, symptoms, and user-specific data.\n\nIt uses an Agentic RAG pipeline to ground responses on user-uploaded documents stored in Supabase.\n\nFeatures:\n\n- FastAPI backend with clean modular architecture\n- LangChain agent with custom tools\n- Supabase pgvecytor for document embeddings and semantic search\n- Agentic RAG ( tool invocation + retrieval )\n- Authentication and per-user data isolation\n- Pydantic schemas\n- Chat endpoint with streaming to improve the perceived responsivenes by creating a faster, more fluid, and human-like interaction.\n- Guardrails for monitoring agent work\n- LangGraph workflows for monthly recommendations\n\nThis is the list of existing endpoints:\n\n\u003ctable\u003e\n  \u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth\u003eVerb\u003c/th\u003e\u003cth\u003eResource\u003c/th\u003e\u003cth\u003eDescription\u003c/th\u003e\u003cth\u003eScope\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd\u003ePOST\u003c/td\u003e\u003ctd\u003e/login\u003c/td\u003e\u003ctd\u003eSupabase sign in\u003c/td\u003e\u003ctd\u003ePublic\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eGET\u003c/td\u003e\u003ctd\u003e/foods\u003c/td\u003e\u003ctd\u003eGet food list\u003c/td\u003e\u003ctd\u003eProtected\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eGET\u003c/td\u003e\u003ctd\u003e/foods/:id\u003c/td\u003e\u003ctd\u003eGet a single food\u003c/td\u003e\u003ctd\u003eProtected\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003ePOST\u003c/td\u003e\u003ctd\u003e/foods\u003c/td\u003e\u003ctd\u003eCreate a food\u003c/td\u003e\u003ctd\u003eProtected\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003ePUT\u003c/td\u003e\u003ctd\u003e/foods/:id\u003c/td\u003e\u003ctd\u003eUpdate food\u003c/td\u003e\u003ctd\u003eProtected\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eDELETE\u003c/td\u003e\u003ctd\u003e/foods/:id\u003c/td\u003e\u003ctd\u003eDelete food\u003c/td\u003e\u003ctd\u003eProtected\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eGET\u003c/td\u003e\u003ctd\u003e/meals\u003c/td\u003e\u003ctd\u003eGet meal list\u003c/td\u003e\u003ctd\u003eProtected\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eGET\u003c/td\u003e\u003ctd\u003e/meals/:id\u003c/td\u003e\u003ctd\u003eGet a single meal\u003c/td\u003e\u003ctd\u003eProtected\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003ePOST\u003c/td\u003e\u003ctd\u003e/meals\u003c/td\u003e\u003ctd\u003eCreate a meal\u003c/td\u003e\u003ctd\u003eProtected\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003ePUT\u003c/td\u003e\u003ctd\u003e/meals/:id\u003c/td\u003e\u003ctd\u003eUpdate meal\u003c/td\u003e\u003ctd\u003eProtected\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eDELETE\u003c/td\u003e\u003ctd\u003e/meals/:id\u003c/td\u003e\u003ctd\u003eDelete a meal\u003c/td\u003e\u003ctd\u003eProtected\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eGET\u003c/td\u003e\u003ctd\u003e/symptoms\u003c/td\u003e\u003ctd\u003eGet symptom list\u003c/td\u003e\u003ctd\u003eProtected\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eGET\u003c/td\u003e\u003ctd\u003e/symptoms/:id\u003c/td\u003e\u003ctd\u003eGet a single symptom\u003c/td\u003e\u003ctd\u003eProtected\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003ePOST\u003c/td\u003e\u003ctd\u003e/symptoms\u003c/td\u003e\u003ctd\u003eCreate a symptom\u003c/td\u003e\u003ctd\u003eProtected\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003ePUT\u003c/td\u003e\u003ctd\u003e/symptoms/:id\u003c/td\u003e\u003ctd\u003eUpdate a symptom\u003c/td\u003e\u003ctd\u003eProtected\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eDELETE\u003c/td\u003e\u003ctd\u003e/symptoms/:id\u003c/td\u003e\u003ctd\u003eDelete a symptom\u003c/td\u003e\u003ctd\u003eProtected\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003ePOST\u003c/td\u003e\u003ctd\u003e/documents\u003c/td\u003e\u003ctd\u003eUploads a document\u003c/td\u003e\u003ctd\u003eProtected\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003ePOST\u003c/td\u003e\u003ctd\u003e/chat\u003c/td\u003e\u003ctd\u003eSends a message to the agent\u003c/td\u003e\u003ctd\u003eProtected\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003ePOST\u003c/td\u003e\u003ctd\u003e/insights\u003c/td\u003e\u003ctd\u003eGathers monthly insights per user\u003c/td\u003e\u003ctd\u003eHidden\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n### Retrieval-Augmented Generation (RAG)  Evaluation\n\nI evaluated the quality of this pipeline using **RAGAS**, focusing on grounding, retrieval quality, and answer relevance.\n\n**Results:**\n\n| Metric              | Score  |\n|---------------------|--------|\n| Faithfulness        | 0.93   |\n| Answer Relevancy    | 0.82   |\n| Context Precision   | 1.00   |\n| Context Recall      | 1.00   |\n\n**Interpretation:**\n- The system shows **high faithfulness**, indicating responses are well-grounded in retrieved context.\n- **Perfect context precision and recall** confirm that retrieved documents are both relevant and sufficient.\n- Answer relevancy remains strong while allowing richer, user-friendly responses.\n\n### Workflow\n\nThe GET /insights endpoint is a special endpoint that runs every month. It is triggered by a cron job and its sole purpose is to prepare recommendations for users based on the meals and symptoms caused by them in the last month.\n\nYou can see the process summarized in the image below:\n\n![insights](insights.png \"insights\")\n\n#### The Process Flow\n\n1. Scheduled Trigger\n\nA cron job runs on the first of every month (automated scheduling)\n\n2. Insights Generation\n\nThe cron job makes a POST /insights request to the API endpoint,\nwhich triggers the AnalystAgent and OutputAgent workflow.\n\n3. Dual Database Operations\n\nUpserts to email_jobs table: Stores the email job record with user info, content, and status\nQueue message: Sends a message to the email_jobs queue for processing\n\n4. Asynchronous Processing\n\nJobs are queued for background processing (using PostgreSQL's pgmq - PostgreSQL Message Queue)\n\n5. Email Delivery\n\nA background worker processes the queue and sends the actual emails\n\nKey Architecture Benefits:\n- Reliability: Database record ensures no emails are lost\n- Idempotency: Upsert prevents duplicate emails for the same user/period\n- Scalability: Async queue handles email delivery without blocking the API\n- Monitoring: Database records allow tracking of email status (PENDING/SENT/FAILED)\n\nThe diagram of the workflow is as follows:\n\n![workflow](workflow.png \"workflow\")\n\nAs you can see it's simply a graph with two nodes:\n\n#### Analysis Node(AnalystAgent)\n\nThe analysis node is responsible for:\n\n**Data Analysis**: Acts as an expert histamine allergy data analyst that processes user data to identify patterns and correlations between foods consumed and symptoms experienced.\n\n**Tool Usage**: Has access to specialized tools (via create_tools(db)) that can query the database to gather necessary food and symptom data for a specific user.\n\n**Insight Generation**: Analyzes which foods a user should avoid and which ones they should consume more of based on their symptom patterns.\n\n**Data Processing**: Takes a user ID as input and performs deep analysis by invoking: \"Which foods the user {user_id} should avoid and which ones they should eat more of based on their symptoms.\"\n\n**Raw Analysis Output**: Returns detailed analytical findings that serve as input for the next stage.\n\n#### Output Node(OutputAgent)\n\nThe output node is responsible for:\n\n**Content Formatting**: Takes the raw analysis from the analyst and transforms it into user-friendly, digestible insights.\n\n**User Experience**: Ensures the recommendations are clear, actionable, and empathetic to users dealing with histamine allergies.\n\n**Content Constraints**: Applies specific formatting rules:\n\nMaximum 8 bullet points\nEach bullet point limited to 20 words\nUses simple, accessible language\nMaintains a neutral, clear tone\nNo Additional Analysis: Focuses solely on presentation and communication rather than performing new analysis.\n\n**Final Output**: Produces the final insights that will be delivered to the user.\n\n\n### :rocket: Deployment\n\nBefore deployment you must containerize the application, the approach I followed was pushing it to dockerhub and then pulling it from there.\n\n```shell\ndocker buildx build --platform linux/amd64,linux/arm64 -t username/food-tracker:v1.0 --push .\n```\n\nThis project uses [Terraform](https://developer.hashicorp.com/terraform) to declaratively provision and manage the cloud infrastructure on Google Cloud Platform (GCP).\n\nThe API is deployed as a containerized service on could run, providing a fully managed, serverless runtime with automatic scaling and zero server maintenance.\n\n#### Infrastructure as Code\n\nIn the infra folder you will see that infrastructure is defined using [Terraform](https://developer.hashicorp.com/terraform), allowing the environment to be:\n\n- Reproducible\n- Version-controlled\n- Easy to review and modify\n\nThe configuration provisions:\n\n- A cloud run service running the api container\n- Public access via IAM (roles/run.invoker)\n- Environment variables required by the application\n\n#### Deployment Flow\n\n1. Build and publish the docker image as mentioned above\n2. Authenticate with google cloud:\n  ```shell\n  gcloud auth login\n  gcloud auth application-default login\n  ```\n3. Initialize and apply the terraform configuration:\n  ```shell\n  terraform init\n  terraform apply\n  ```\n\nThis setup allows the application to be deployed and updated with minimal operational overhead while remaining scalable and production-ready.\n\n### How to run it locally ?\n\nClone the repository\n\n```shell\ngit clone food-tracker-api\n```\n\nCreate a virtual environment\n\n```shell\npython3 -m venv food-tracker-env\n```\n\nActivate it\n\n```shell\nsource food-tracker-env/bin/activate\n```\n\nInstall your exact dependencies\n\n```shell\npip install -r requirements.txt\n```\n\nRun it\n\n```shell\nfastapi dev main.py\n```\n\n### How to run unit tests ?\n\nYou can run the unit tests by issuing the following command:\n\n```shell\npytest\n```\n\n### Contributing\n\nPull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.\n\n### License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feiberham%2Ffood-tracker-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feiberham%2Ffood-tracker-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feiberham%2Ffood-tracker-api/lists"}