diff --git a/python/agent/crew-ai/src/main.py b/python/agent/crew-ai/src/main.py index 62243f3b..38c33a5c 100644 --- a/python/agent/crew-ai/src/main.py +++ b/python/agent/crew-ai/src/main.py @@ -1,4 +1,7 @@ import wikipedia +import os +from pathlib import Path +from dotenv import load_dotenv, find_dotenv from crewai import Agent, Crew, Process, Task from crewai.tools import BaseTool as CrewAITool from langchain_community.tools import DuckDuckGoSearchRun, WikipediaQueryRun @@ -6,6 +9,11 @@ from observability import setup_observability from pydantic import Field +# 1) load global/shared first +load_dotenv(os.path.expanduser("~/.config/secrets/myapps.env"), override=False) +# 2) then load per-app .env (if present) to override selectively +load_dotenv(find_dotenv(usecwd=True), override=True) + setup_observability() diff --git a/python/agent/langchain-agent/main.py b/python/agent/langchain-agent/main.py index 09e46a4d..a7580bdb 100644 --- a/python/agent/langchain-agent/main.py +++ b/python/agent/langchain-agent/main.py @@ -1,4 +1,5 @@ -from dotenv import load_dotenv +from pathlib import Path +from dotenv import load_dotenv, find_dotenv from langchain.agents import initialize_agent, Tool from langchain.agents.agent_types import AgentType from langchain_openai import ChatOpenAI @@ -7,8 +8,10 @@ from galileo.handlers.langchain import GalileoCallback import os -# Load environment variables (e.g., API keys) -load_dotenv() +# 1) load global/shared first +load_dotenv(os.path.expanduser("~/.config/secrets/myapps.env"), override=False) +# 2) then load per-app .env (if present) to override selectively +load_dotenv(find_dotenv(usecwd=True), override=True) # Define a tool for the agent to use diff --git a/python/agent/langgraph-fsi-agent/after/app.py b/python/agent/langgraph-fsi-agent/after/app.py index 4a8b6f3d..6a7c481e 100644 --- a/python/agent/langgraph-fsi-agent/after/app.py +++ b/python/agent/langgraph-fsi-agent/after/app.py @@ -10,7 +10,9 @@ from langchain_core.callbacks import Callbacks from langchain_core.messages import HumanMessage, AIMessage -from dotenv import load_dotenv +import os +from pathlib import Path +from dotenv import load_dotenv, find_dotenv from galileo import galileo_context from galileo.handlers.langchain import GalileoAsyncCallback @@ -19,8 +21,10 @@ create_supervisor_agent, ) -# Load environment variables from .env file -load_dotenv() +# 1) load global/shared first +load_dotenv(os.path.expanduser("~/.config/secrets/myapps.env"), override=False) +# 2) then load per-app .env (if present) to override selectively +load_dotenv(find_dotenv(usecwd=True), override=True) # Build the agent graph diff --git a/python/agent/langgraph-fsi-agent/before/app.py b/python/agent/langgraph-fsi-agent/before/app.py index c4387c72..12bd7740 100644 --- a/python/agent/langgraph-fsi-agent/before/app.py +++ b/python/agent/langgraph-fsi-agent/before/app.py @@ -10,14 +10,18 @@ from langchain_core.callbacks import Callbacks from langchain_core.messages import HumanMessage, AIMessage -from dotenv import load_dotenv +import os +from pathlib import Path +from dotenv import load_dotenv, find_dotenv from src.galileo_langgraph_fsi_agent.agents.supervisor_agent import ( create_supervisor_agent, ) -# Load environment variables from .env file -load_dotenv() +# 1) load global/shared first +load_dotenv(os.path.expanduser("~/.config/secrets/myapps.env"), override=False) +# 2) then load per-app .env (if present) to override selectively +load_dotenv(find_dotenv(usecwd=True), override=True) # Build the agent graph diff --git a/python/agent/minimal-agent-example/app.py b/python/agent/minimal-agent-example/app.py index e359b6c9..b9325e3f 100644 --- a/python/agent/minimal-agent-example/app.py +++ b/python/agent/minimal-agent-example/app.py @@ -8,9 +8,13 @@ from pydantic import BaseModel import json from typing import Callable -from dotenv import load_dotenv +from pathlib import Path +from dotenv import load_dotenv, find_dotenv -load_dotenv() +# 1) load global/shared first +load_dotenv(os.path.expanduser("~/.config/secrets/myapps.env"), override=False) +# 2) then load per-app .env (if present) to override selectively +load_dotenv(find_dotenv(usecwd=True), override=True) client = openai.OpenAI(api_key=os.environ.get("OPENAI_API_KEY")) diff --git a/python/agent/startup-simulator-3000/agent.py b/python/agent/startup-simulator-3000/agent.py index 806ac6b7..4eb62553 100644 --- a/python/agent/startup-simulator-3000/agent.py +++ b/python/agent/startup-simulator-3000/agent.py @@ -8,7 +8,8 @@ import json from typing import Dict, Any, List, Optional from datetime import datetime -from dotenv import load_dotenv +from pathlib import Path +from dotenv import load_dotenv, find_dotenv from galileo import GalileoLogger from galileo.openai import openai @@ -27,8 +28,10 @@ from tools.text_analysis import TextAnalyzerTool from tools.keyword_extraction import KeywordExtractorTool -# Load environment variables -load_dotenv() +# 1) load global/shared first +load_dotenv(os.path.expanduser("~/.config/secrets/myapps.env"), override=False) +# 2) then load per-app .env (if present) to override selectively +load_dotenv(find_dotenv(usecwd=True), override=True) # Use the Galileo-wrapped OpenAI client client = openai.OpenAI(api_key=os.environ.get("OPENAI_API_KEY")) diff --git a/python/agent/weather-vibes-agent/00-tutorial/01-weather-vibes-overview.md b/python/agent/weather-vibes-agent/00-tutorial/01-weather-vibes-overview.md index e96afc73..d82e3df7 100644 --- a/python/agent/weather-vibes-agent/00-tutorial/01-weather-vibes-overview.md +++ b/python/agent/weather-vibes-agent/00-tutorial/01-weather-vibes-overview.md @@ -9,8 +9,8 @@ Before we dive into the code ocean, make sure you've packed: - **Python 3.8+** installed on your system - **API Keys** (free options available): - OpenAI API key (for agent reasoning) - - WeatherAPI key (for weather data) - - YouTube API key (for video recommendations) + - WeatherAPI key (for weather data https://www.weatherapi.com/) + - YouTube V3 API key (for video recommendations) - Galileo API key (for monitoring and evaluation) - **Development Environment**: - Code editor of choice diff --git a/python/agent/weather-vibes-agent/agent.py b/python/agent/weather-vibes-agent/agent.py index 30a3b31f..5f986dc9 100644 --- a/python/agent/weather-vibes-agent/agent.py +++ b/python/agent/weather-vibes-agent/agent.py @@ -13,11 +13,14 @@ import os import sys from pathlib import Path -from dotenv import load_dotenv +from dotenv import load_dotenv, find_dotenv from galileo import log, galileo_context -# Load environment variables & set up path -load_dotenv() +# 1) load global/shared secrets first +load_dotenv(os.path.expanduser("~/.config/secrets/myapps.env"), override=False) +# 2) then load per-app .env (if present) to override selectively +load_dotenv(find_dotenv(usecwd=True), override=True) +#setup path sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) # Quick environment check diff --git a/python/chatbot/basic-examples/app.py b/python/chatbot/basic-examples/app.py index f1b003a4..ddd17538 100644 --- a/python/chatbot/basic-examples/app.py +++ b/python/chatbot/basic-examples/app.py @@ -1,9 +1,13 @@ import os from galileo import openai, logger # The Galileo OpenAI client wrapper is all you need! -from dotenv import load_dotenv +from dotenv import load_dotenv ,find_dotenv -load_dotenv() +# Load environment variables +# 1) load global/shared first +load_dotenv(os.path.expanduser("~/.config/secrets/myapps.env"), override=False) +# 2) then load per-app .env (if present) to override selectively +load_dotenv(find_dotenv(usecwd=True), override=True) client = openai.OpenAI( api_key=os.environ.get("OPENAI_API_KEY"), diff --git a/python/chatbot/basic-examples/hallucination.py b/python/chatbot/basic-examples/hallucination.py index 39aeb961..d0703e96 100644 --- a/python/chatbot/basic-examples/hallucination.py +++ b/python/chatbot/basic-examples/hallucination.py @@ -3,9 +3,13 @@ import time import openai # Using the standard OpenAI library from galileo import GalileoLogger # Import GalileoLogger for logging -from dotenv import load_dotenv +from dotenv import load_dotenv, find_dotenv -load_dotenv() +# Load environment variables +# 1) load global/shared first +load_dotenv(os.path.expanduser("~/.config/secrets/myapps.env"), override=False) +# 2) then load per-app .env (if present) to override selectively +load_dotenv(find_dotenv(usecwd=True), override=True) # Initialize the GalileoLogger logger = GalileoLogger(project="hallucination", log_stream="dev") diff --git a/python/chatbot/basic-examples/test.py b/python/chatbot/basic-examples/test.py index c6eec93c..2270aa33 100644 --- a/python/chatbot/basic-examples/test.py +++ b/python/chatbot/basic-examples/test.py @@ -3,9 +3,13 @@ import openai # Using the standard OpenAI library from galileo import GalileoLogger # Import GalileoLogger for logging -from dotenv import load_dotenv +from dotenv import load_dotenv, find_dotenv -load_dotenv() +# Load environment variables +# 1) load global/shared first +load_dotenv(os.path.expanduser("~/.config/secrets/myapps.env"), override=False) +# 2) then load per-app .env (if present) to override selectively +load_dotenv(find_dotenv(usecwd=True), override=True) # Initialize the GalileoLogger logger = GalileoLogger(project="chatbot", log_stream="test") diff --git a/python/chatbot/sample-project-chatbot/anthropic/app.py b/python/chatbot/sample-project-chatbot/anthropic/app.py index b8d31406..5c372b18 100644 --- a/python/chatbot/sample-project-chatbot/anthropic/app.py +++ b/python/chatbot/sample-project-chatbot/anthropic/app.py @@ -30,13 +30,15 @@ from anthropic import Anthropic -from dotenv import load_dotenv +from dotenv import load_dotenv, find_dotenv from galileo import galileo_context, log -# Load the environment variables from the .env file -# This will override any existing environment variables with the same name -load_dotenv(override=True) +# Load environment variables +# 1) load global/shared first +load_dotenv(os.path.expanduser("~/.config/secrets/myapps.env"), override=False) +# 2) then load per-app .env (if present) to override selectively +load_dotenv(find_dotenv(usecwd=True), override=True) # Set the model name from the environment variable # If this is not set, raise an exception diff --git a/python/chatbot/sample-project-chatbot/anthropic/test.py b/python/chatbot/sample-project-chatbot/anthropic/test.py index 31168a05..b3e55309 100644 --- a/python/chatbot/sample-project-chatbot/anthropic/test.py +++ b/python/chatbot/sample-project-chatbot/anthropic/test.py @@ -10,7 +10,7 @@ import os import time -from dotenv import load_dotenv +from dotenv import load_dotenv, find_dotenv from galileo import GalileoScorers from galileo.datasets import create_dataset, get_dataset @@ -27,8 +27,11 @@ def setup_module(): """ print("Setting up test environment...") - # Load the environment variables from the .env file - load_dotenv() + # Load environment variables + # 1) load global/shared first + load_dotenv(os.path.expanduser("~/.config/secrets/myapps.env"), override=False) + # 2) then load per-app .env (if present) to override selectively + load_dotenv(find_dotenv(usecwd=True), override=True) # Verify required environment variables are set # You will also need to set up the environment variables for your OpenAI API connection. diff --git a/python/chatbot/sample-project-chatbot/azure-inference/app.py b/python/chatbot/sample-project-chatbot/azure-inference/app.py index 271c12b2..d9345aca 100644 --- a/python/chatbot/sample-project-chatbot/azure-inference/app.py +++ b/python/chatbot/sample-project-chatbot/azure-inference/app.py @@ -33,13 +33,15 @@ from azure.ai.inference.models import SystemMessage, UserMessage, AssistantMessage from azure.core.credentials import AzureKeyCredential -from dotenv import load_dotenv +from dotenv import load_dotenv, find_dotenv from galileo import galileo_context, log -# Load the environment variables from the .env file -# This will override any existing environment variables with the same name -load_dotenv(override=True) +# Load environment variables +# 1) load global/shared first +load_dotenv(os.path.expanduser("~/.config/secrets/myapps.env"), override=False) +# 2) then load per-app .env (if present) to override selectively +load_dotenv(find_dotenv(usecwd=True), override=True) # Set the model name from the environment variable # If this is not set, raise an exception diff --git a/python/chatbot/sample-project-chatbot/azure-inference/test.py b/python/chatbot/sample-project-chatbot/azure-inference/test.py index 31168a05..b3e55309 100644 --- a/python/chatbot/sample-project-chatbot/azure-inference/test.py +++ b/python/chatbot/sample-project-chatbot/azure-inference/test.py @@ -10,7 +10,7 @@ import os import time -from dotenv import load_dotenv +from dotenv import load_dotenv, find_dotenv from galileo import GalileoScorers from galileo.datasets import create_dataset, get_dataset @@ -27,8 +27,11 @@ def setup_module(): """ print("Setting up test environment...") - # Load the environment variables from the .env file - load_dotenv() + # Load environment variables + # 1) load global/shared first + load_dotenv(os.path.expanduser("~/.config/secrets/myapps.env"), override=False) + # 2) then load per-app .env (if present) to override selectively + load_dotenv(find_dotenv(usecwd=True), override=True) # Verify required environment variables are set # You will also need to set up the environment variables for your OpenAI API connection. diff --git a/python/chatbot/sample-project-chatbot/openai-ollama/app.py b/python/chatbot/sample-project-chatbot/openai-ollama/app.py index f53e72a5..a910431e 100644 --- a/python/chatbot/sample-project-chatbot/openai-ollama/app.py +++ b/python/chatbot/sample-project-chatbot/openai-ollama/app.py @@ -31,14 +31,16 @@ from datetime import datetime import os -from dotenv import load_dotenv +from dotenv import load_dotenv, find_dotenv from galileo import galileo_context, log from galileo.openai import OpenAI -# Load the environment variables from the .env file -# This will override any existing environment variables with the same name -load_dotenv(override=True) +# Load environment variables +# 1) load global/shared first +load_dotenv(os.path.expanduser("~/.config/secrets/myapps.env"), override=False) +# 2) then load per-app .env (if present) to override selectively +load_dotenv(find_dotenv(usecwd=True), override=True) # Set the model name from the environment variable # If this is not set, raise an exception diff --git a/python/chatbot/sample-project-chatbot/openai-ollama/test.py b/python/chatbot/sample-project-chatbot/openai-ollama/test.py index 31168a05..b3e55309 100644 --- a/python/chatbot/sample-project-chatbot/openai-ollama/test.py +++ b/python/chatbot/sample-project-chatbot/openai-ollama/test.py @@ -10,7 +10,7 @@ import os import time -from dotenv import load_dotenv +from dotenv import load_dotenv, find_dotenv from galileo import GalileoScorers from galileo.datasets import create_dataset, get_dataset @@ -27,8 +27,11 @@ def setup_module(): """ print("Setting up test environment...") - # Load the environment variables from the .env file - load_dotenv() + # Load environment variables + # 1) load global/shared first + load_dotenv(os.path.expanduser("~/.config/secrets/myapps.env"), override=False) + # 2) then load per-app .env (if present) to override selectively + load_dotenv(find_dotenv(usecwd=True), override=True) # Verify required environment variables are set # You will also need to set up the environment variables for your OpenAI API connection. diff --git a/typescript/agent/langgraph-fsi-agent/app.test.ts b/typescript/agent/langgraph-fsi-agent/app.test.ts index 1d057377..48501c8d 100644 --- a/typescript/agent/langgraph-fsi-agent/app.test.ts +++ b/typescript/agent/langgraph-fsi-agent/app.test.ts @@ -1,5 +1,5 @@ import { createDataset, GalileoCallback, GalileoScorers, getDataset, getLogger, runExperiment } from "galileo"; -import dotenv from 'dotenv'; +import "./src/config/env"; // side-effect: loads env vars import fs from 'fs'; import path from 'path'; @@ -35,8 +35,6 @@ const sendInputToLlm = async (datasetRow: any): Promise => { describe('Chatbot Galileo Tests', () => { beforeAll(async () => { - // Load environment variables from .env file - dotenv.config(); // Verify required environment variables are set // You will also need to set up the environment variables for your OpenAI API connection. diff --git a/typescript/agent/langgraph-fsi-agent/app.ts b/typescript/agent/langgraph-fsi-agent/app.ts index a848cacd..d61bbf17 100644 --- a/typescript/agent/langgraph-fsi-agent/app.ts +++ b/typescript/agent/langgraph-fsi-agent/app.ts @@ -1,24 +1,22 @@ /** * A demo Financial Services Agent using LangGraph, with Galileo as the evaluation platform. */ +import "./src/config/env"; // side-effect: loads env vars import * as readline from 'readline'; import { getLogger, GalileoCallback } from "galileo"; import { createSupervisorAgent } from './agents/supervisorAgent'; -// Load environment variables from .env file -import dotenv from 'dotenv'; -dotenv.config(); // Validate required environment variables -const requiredEnvVars = { - GALILEO_API_KEY: process.env.GALILEO_API_KEY, - GALILEO_PROJECT: process.env.GALILEO_PROJECT, - GALILEO_LOG_STREAM: process.env.GALILEO_LOG_STREAM, - MODEL_NAME: process.env.MODEL_NAME, - PINECONE_API_KEY: process.env.PINECONE_API_KEY, - OPENAI_API_KEY: process.env.OPENAI_API_KEY, -}; +const required = [ + "GALILEO_API_KEY", + "GALILEO_PROJECT", + "GALILEO_LOG_STREAM", + "MODEL_NAME", + "PINECONE_API_KEY", + "OPENAI_API_KEY", +] as const; for (const [key, value] of Object.entries(requiredEnvVars)) { if (!value) { diff --git a/typescript/agent/langgraph-fsi-agent/src/config/env.ts b/typescript/agent/langgraph-fsi-agent/src/config/env.ts new file mode 100644 index 00000000..c94275f4 --- /dev/null +++ b/typescript/agent/langgraph-fsi-agent/src/config/env.ts @@ -0,0 +1,20 @@ +// src/config/env.ts +import fs from "node:fs"; +import path from "node:path"; +import os from "node:os"; +import dotenv from "dotenv"; +import dotenvFlow from "dotenv-flow"; + +// 1) Load a shared file FIRST (lowest precedence among files) +// Real env vars in process.env always win. +const shared = path.join(os.homedir(), ".config", "secrets", "myapps.env"); +if (fs.existsSync(shared)) { + dotenv.config({ path: shared, override: false }); +} + +// 2) Let dotenv-flow load the standard cascade for the project: +// .env -> .env.local -> .env.[NODE_ENV] -> .env.[NODE_ENV].local +dotenvFlow.config({ + node_env: process.env.NODE_ENV, // e.g. "development", "test", "production" + silent: true, // don’t log missing files +}); \ No newline at end of file diff --git a/typescript/agent/mastra-template-csv-to-questions/src/config/env.ts b/typescript/agent/mastra-template-csv-to-questions/src/config/env.ts new file mode 100644 index 00000000..c94275f4 --- /dev/null +++ b/typescript/agent/mastra-template-csv-to-questions/src/config/env.ts @@ -0,0 +1,20 @@ +// src/config/env.ts +import fs from "node:fs"; +import path from "node:path"; +import os from "node:os"; +import dotenv from "dotenv"; +import dotenvFlow from "dotenv-flow"; + +// 1) Load a shared file FIRST (lowest precedence among files) +// Real env vars in process.env always win. +const shared = path.join(os.homedir(), ".config", "secrets", "myapps.env"); +if (fs.existsSync(shared)) { + dotenv.config({ path: shared, override: false }); +} + +// 2) Let dotenv-flow load the standard cascade for the project: +// .env -> .env.local -> .env.[NODE_ENV] -> .env.[NODE_ENV].local +dotenvFlow.config({ + node_env: process.env.NODE_ENV, // e.g. "development", "test", "production" + silent: true, // don’t log missing files +}); \ No newline at end of file diff --git a/typescript/agent/mastra-template-csv-to-questions/src/mastra/index.ts b/typescript/agent/mastra-template-csv-to-questions/src/mastra/index.ts index 793b8cf5..04820479 100644 --- a/typescript/agent/mastra-template-csv-to-questions/src/mastra/index.ts +++ b/typescript/agent/mastra-template-csv-to-questions/src/mastra/index.ts @@ -1,3 +1,4 @@ +import "../config/env"; // side-effect: loads env vars import { OpenInferenceOTLPTraceExporter, isOpenInferenceSpan, diff --git a/typescript/agent/minimal-agent-example/minimal_agent.ts b/typescript/agent/minimal-agent-example/minimal_agent.ts index f79f21b7..d5518c08 100644 --- a/typescript/agent/minimal-agent-example/minimal_agent.ts +++ b/typescript/agent/minimal-agent-example/minimal_agent.ts @@ -1,4 +1,4 @@ -import * as dotenv from 'dotenv'; +import "./config/env"; // side-effect: loads env vars import * as fs from 'fs'; import * as path from 'path'; import { OpenAI } from 'openai'; @@ -6,8 +6,6 @@ import { log, wrapOpenAI, init, flush } from 'galileo'; import chalk from 'chalk'; import inquirer from 'inquirer'; -// Load environment variables -dotenv.config(); // Suppress any warnings if needed // process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; diff --git a/typescript/agent/minimal-agent-example/src/config/env.ts b/typescript/agent/minimal-agent-example/src/config/env.ts new file mode 100644 index 00000000..c94275f4 --- /dev/null +++ b/typescript/agent/minimal-agent-example/src/config/env.ts @@ -0,0 +1,20 @@ +// src/config/env.ts +import fs from "node:fs"; +import path from "node:path"; +import os from "node:os"; +import dotenv from "dotenv"; +import dotenvFlow from "dotenv-flow"; + +// 1) Load a shared file FIRST (lowest precedence among files) +// Real env vars in process.env always win. +const shared = path.join(os.homedir(), ".config", "secrets", "myapps.env"); +if (fs.existsSync(shared)) { + dotenv.config({ path: shared, override: false }); +} + +// 2) Let dotenv-flow load the standard cascade for the project: +// .env -> .env.local -> .env.[NODE_ENV] -> .env.[NODE_ENV].local +dotenvFlow.config({ + node_env: process.env.NODE_ENV, // e.g. "development", "test", "production" + silent: true, // don’t log missing files +}); \ No newline at end of file diff --git a/typescript/agent/stripe-agent-tool/src/config/environment.ts b/typescript/agent/stripe-agent-tool/src/config/environment.ts index 1565d699..e7574e43 100644 --- a/typescript/agent/stripe-agent-tool/src/config/environment.ts +++ b/typescript/agent/stripe-agent-tool/src/config/environment.ts @@ -1,7 +1,22 @@ -import { config } from 'dotenv'; +import fs from "node:fs"; +import path from "node:path"; +import os from "node:os"; +import dotenv from "dotenv"; +import dotenvFlow from "dotenv-flow"; -// Load environment variables -config(); +// 1) Load a shared file FIRST (lowest precedence among files) +// Real env vars in process.env always win. +const shared = path.join(os.homedir(), ".config", "secrets", "myapps.env"); +if (fs.existsSync(shared)) { + dotenv.config({ path: shared, override: false }); +} + +// 2) Let dotenv-flow load the standard cascade for the project: +// .env -> .env.local -> .env.[NODE_ENV] -> .env.[NODE_ENV].local +dotenvFlow.config({ + node_env: process.env.NODE_ENV, // e.g. "development", "test", "production" + silent: true, // don’t log missing files +}); export interface EnvironmentConfig { stripe: { diff --git a/typescript/agent/stripe-agent-tool/tests/setup.ts b/typescript/agent/stripe-agent-tool/tests/setup.ts index bf5bd338..d795fb48 100644 --- a/typescript/agent/stripe-agent-tool/tests/setup.ts +++ b/typescript/agent/stripe-agent-tool/tests/setup.ts @@ -1,8 +1,5 @@ // Global test setup -import { config } from 'dotenv'; - -// Load environment variables for testing -config(); +import "./config/environment"; // side-effect: loads env va // Mock environment variables if not set process.env.STRIPE_SECRET_KEY = process.env.STRIPE_SECRET_KEY || 'sk_test_mock_key'; diff --git a/typescript/chatbot/sample-project-chatbot/anthropic/app.test.ts b/typescript/chatbot/sample-project-chatbot/anthropic/app.test.ts index 54d557e7..8bc87de0 100644 --- a/typescript/chatbot/sample-project-chatbot/anthropic/app.test.ts +++ b/typescript/chatbot/sample-project-chatbot/anthropic/app.test.ts @@ -1,5 +1,5 @@ +import "./src/config/env"; // side-effect: loads env vars import { createDataset, GalileoScorers, getDataset, runExperiment } from "galileo"; -import dotenv from 'dotenv'; import { chatWithLLM } from "./chat"; import fs from 'fs'; import path from 'path'; @@ -17,8 +17,6 @@ const sendInputToLlm = async (datasetRow: any): Promise => { describe('Chatbot Galileo Tests', () => { beforeAll(async () => { - // Load environment variables from .env file - dotenv.config(); // Verify required environment variables are set // You will also need to set up the environment variables for your OpenAI API connection. diff --git a/typescript/chatbot/sample-project-chatbot/anthropic/chat.ts b/typescript/chatbot/sample-project-chatbot/anthropic/chat.ts index 8eba45de..b88f0ed4 100644 --- a/typescript/chatbot/sample-project-chatbot/anthropic/chat.ts +++ b/typescript/chatbot/sample-project-chatbot/anthropic/chat.ts @@ -1,11 +1,8 @@ +import "./src/config/env"; // side-effect: loads env vars import Anthropic from '@anthropic-ai/sdk'; import { getLogger, log } from "galileo"; -// Load environment variables from .env file -import dotenv from 'dotenv'; -dotenv.config(); - // Validate required environment variables const requiredEnvVars = { GALILEO_API_KEY: process.env.GALILEO_API_KEY, diff --git a/typescript/chatbot/sample-project-chatbot/anthropic/src/config/env.ts b/typescript/chatbot/sample-project-chatbot/anthropic/src/config/env.ts new file mode 100644 index 00000000..c94275f4 --- /dev/null +++ b/typescript/chatbot/sample-project-chatbot/anthropic/src/config/env.ts @@ -0,0 +1,20 @@ +// src/config/env.ts +import fs from "node:fs"; +import path from "node:path"; +import os from "node:os"; +import dotenv from "dotenv"; +import dotenvFlow from "dotenv-flow"; + +// 1) Load a shared file FIRST (lowest precedence among files) +// Real env vars in process.env always win. +const shared = path.join(os.homedir(), ".config", "secrets", "myapps.env"); +if (fs.existsSync(shared)) { + dotenv.config({ path: shared, override: false }); +} + +// 2) Let dotenv-flow load the standard cascade for the project: +// .env -> .env.local -> .env.[NODE_ENV] -> .env.[NODE_ENV].local +dotenvFlow.config({ + node_env: process.env.NODE_ENV, // e.g. "development", "test", "production" + silent: true, // don’t log missing files +}); \ No newline at end of file diff --git a/typescript/chatbot/sample-project-chatbot/azure-inference/app.test.ts b/typescript/chatbot/sample-project-chatbot/azure-inference/app.test.ts index 54d557e7..8bc87de0 100644 --- a/typescript/chatbot/sample-project-chatbot/azure-inference/app.test.ts +++ b/typescript/chatbot/sample-project-chatbot/azure-inference/app.test.ts @@ -1,5 +1,5 @@ +import "./src/config/env"; // side-effect: loads env vars import { createDataset, GalileoScorers, getDataset, runExperiment } from "galileo"; -import dotenv from 'dotenv'; import { chatWithLLM } from "./chat"; import fs from 'fs'; import path from 'path'; @@ -17,8 +17,6 @@ const sendInputToLlm = async (datasetRow: any): Promise => { describe('Chatbot Galileo Tests', () => { beforeAll(async () => { - // Load environment variables from .env file - dotenv.config(); // Verify required environment variables are set // You will also need to set up the environment variables for your OpenAI API connection. diff --git a/typescript/chatbot/sample-project-chatbot/azure-inference/chat.ts b/typescript/chatbot/sample-project-chatbot/azure-inference/chat.ts index 303be032..3e207222 100644 --- a/typescript/chatbot/sample-project-chatbot/azure-inference/chat.ts +++ b/typescript/chatbot/sample-project-chatbot/azure-inference/chat.ts @@ -1,11 +1,9 @@ +import "./src/config/env"; // side-effect: loads env vars import ModelClient from "@azure-rest/ai-inference"; import { AzureKeyCredential } from "@azure/core-auth"; import { getLogger, log } from "galileo"; -// Load environment variables from .env file -import dotenv from 'dotenv'; -dotenv.config(); // Validate required environment variables const requiredEnvVars = { diff --git a/typescript/chatbot/sample-project-chatbot/azure-inference/src/config/env.ts b/typescript/chatbot/sample-project-chatbot/azure-inference/src/config/env.ts new file mode 100644 index 00000000..c94275f4 --- /dev/null +++ b/typescript/chatbot/sample-project-chatbot/azure-inference/src/config/env.ts @@ -0,0 +1,20 @@ +// src/config/env.ts +import fs from "node:fs"; +import path from "node:path"; +import os from "node:os"; +import dotenv from "dotenv"; +import dotenvFlow from "dotenv-flow"; + +// 1) Load a shared file FIRST (lowest precedence among files) +// Real env vars in process.env always win. +const shared = path.join(os.homedir(), ".config", "secrets", "myapps.env"); +if (fs.existsSync(shared)) { + dotenv.config({ path: shared, override: false }); +} + +// 2) Let dotenv-flow load the standard cascade for the project: +// .env -> .env.local -> .env.[NODE_ENV] -> .env.[NODE_ENV].local +dotenvFlow.config({ + node_env: process.env.NODE_ENV, // e.g. "development", "test", "production" + silent: true, // don’t log missing files +}); \ No newline at end of file diff --git a/typescript/chatbot/sample-project-chatbot/openai-ollama/.env.example b/typescript/chatbot/sample-project-chatbot/openai-ollama/.env.example deleted file mode 100644 index 8c61c48e..00000000 --- a/typescript/chatbot/sample-project-chatbot/openai-ollama/.env.example +++ /dev/null @@ -1,12 +0,0 @@ -# Galileo Environment Variables -GALILEO_API_KEY= # Your Galileo API key. -GALILEO_PROJECT=Simple Chatbot # Your Galileo project name. -GALILEO_LOG_STREAM=Default Log Stream # The name of the log stream you want to use for logging. - -# Provide the console url below if you are using a custom deployment, and not using app.galileo.ai -# GALILEO_CONSOLE_URL= # Optional if you are using a hosted version of Galileo - -# OpenAI and compatible LLM Environment Variables -OPENAI_API_KEY= # Your OpenAI API key. If you are using Ollama just set this to ollama -# OPENAI_BASE_URL= # Optional if you are not using the public OpenAI API. If you are using Ollama, set this to http://localhost:11434/v1 -MODEL_NAME= # The name of the model you want to use, e.g. gpt-3.5-turbo, llama2, etc. diff --git a/typescript/chatbot/sample-project-chatbot/openai-ollama/app.test.ts b/typescript/chatbot/sample-project-chatbot/openai-ollama/app.test.ts index 04159c37..766e631d 100644 --- a/typescript/chatbot/sample-project-chatbot/openai-ollama/app.test.ts +++ b/typescript/chatbot/sample-project-chatbot/openai-ollama/app.test.ts @@ -1,5 +1,5 @@ +import "./src/config/env"; // side-effect: loads env vars import { createDataset, GalileoScorers, getDataset, runExperiment } from "galileo"; -import dotenv from 'dotenv'; import { chatWithLLM } from "./chat"; import fs from 'fs'; import path from 'path'; @@ -17,8 +17,6 @@ const sendInputToLlm = async (datasetRow: any): Promise => { describe('Chatbot Galileo Tests', () => { beforeAll(async () => { - // Load environment variables from .env file - dotenv.config(); // Verify required environment variables are set // You will also need to set up the environment variables for your OpenAI API connection. diff --git a/typescript/chatbot/sample-project-chatbot/openai-ollama/chat.ts b/typescript/chatbot/sample-project-chatbot/openai-ollama/chat.ts index 837eff88..f4be296c 100644 --- a/typescript/chatbot/sample-project-chatbot/openai-ollama/chat.ts +++ b/typescript/chatbot/sample-project-chatbot/openai-ollama/chat.ts @@ -1,10 +1,8 @@ +import "./src/config/env"; // side-effect: loads env vars import { getLogger, log, wrapOpenAI } from "galileo"; import { OpenAI } from "openai"; -// Load environment variables from .env file -import dotenv from 'dotenv'; -dotenv.config(); // Validate required environment variables const requiredEnvVars = { diff --git a/typescript/chatbot/sample-project-chatbot/openai-ollama/package-lock.json b/typescript/chatbot/sample-project-chatbot/openai-ollama/package-lock.json index 5b931c48..a0757104 100644 --- a/typescript/chatbot/sample-project-chatbot/openai-ollama/package-lock.json +++ b/typescript/chatbot/sample-project-chatbot/openai-ollama/package-lock.json @@ -17,7 +17,7 @@ "@types/node": "^24.0.12", "jest": "^29.7.0", "ts-jest": "^29.4.0", - "tsx": "^4.20.3", + "tsx": "^4.20.5", "typescript": "^5.8.3" }, "engines": { @@ -3170,9 +3170,9 @@ } }, "node_modules/form-data": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz", - "integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -6307,9 +6307,9 @@ } }, "node_modules/tsx": { - "version": "4.20.3", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.3.tgz", - "integrity": "sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ==", + "version": "4.20.5", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.5.tgz", + "integrity": "sha512-+wKjMNU9w/EaQayHXb7WA7ZaHY6hN8WgfvHNQ3t1PnU91/7O8TcTnIhCDYTZwnt8JsO9IBqZ30Ln1r7pPF52Aw==", "dev": true, "license": "MIT", "dependencies": { diff --git a/typescript/chatbot/sample-project-chatbot/openai-ollama/package.json b/typescript/chatbot/sample-project-chatbot/openai-ollama/package.json index 204cd999..925ec315 100644 --- a/typescript/chatbot/sample-project-chatbot/openai-ollama/package.json +++ b/typescript/chatbot/sample-project-chatbot/openai-ollama/package.json @@ -22,7 +22,7 @@ "@types/node": "^24.0.12", "jest": "^29.7.0", "ts-jest": "^29.4.0", - "tsx": "^4.20.3", + "tsx": "^4.20.5", "typescript": "^5.8.3" } } diff --git a/typescript/chatbot/sample-project-chatbot/openai-ollama/src/config/env.ts b/typescript/chatbot/sample-project-chatbot/openai-ollama/src/config/env.ts new file mode 100644 index 00000000..c94275f4 --- /dev/null +++ b/typescript/chatbot/sample-project-chatbot/openai-ollama/src/config/env.ts @@ -0,0 +1,20 @@ +// src/config/env.ts +import fs from "node:fs"; +import path from "node:path"; +import os from "node:os"; +import dotenv from "dotenv"; +import dotenvFlow from "dotenv-flow"; + +// 1) Load a shared file FIRST (lowest precedence among files) +// Real env vars in process.env always win. +const shared = path.join(os.homedir(), ".config", "secrets", "myapps.env"); +if (fs.existsSync(shared)) { + dotenv.config({ path: shared, override: false }); +} + +// 2) Let dotenv-flow load the standard cascade for the project: +// .env -> .env.local -> .env.[NODE_ENV] -> .env.[NODE_ENV].local +dotenvFlow.config({ + node_env: process.env.NODE_ENV, // e.g. "development", "test", "production" + silent: true, // don’t log missing files +}); \ No newline at end of file diff --git a/typescript/datasets-experiments/index.ts b/typescript/datasets-experiments/index.ts index fcc01043..a2cb18ba 100644 --- a/typescript/datasets-experiments/index.ts +++ b/typescript/datasets-experiments/index.ts @@ -1,9 +1,7 @@ +import "./src/config/env"; // side-effect: loads env vars import { createDataset, getDataset, runExperiment, wrapOpenAI, createPromptTemplate } from "galileo"; import { MessageRole } from "galileo/dist/types/message.types"; import { OpenAI } from 'openai'; -import { config } from "dotenv"; - -config(); const projectName = "datasets-experiments"; diff --git a/typescript/datasets-experiments/src/config/env.ts b/typescript/datasets-experiments/src/config/env.ts new file mode 100644 index 00000000..c94275f4 --- /dev/null +++ b/typescript/datasets-experiments/src/config/env.ts @@ -0,0 +1,20 @@ +// src/config/env.ts +import fs from "node:fs"; +import path from "node:path"; +import os from "node:os"; +import dotenv from "dotenv"; +import dotenvFlow from "dotenv-flow"; + +// 1) Load a shared file FIRST (lowest precedence among files) +// Real env vars in process.env always win. +const shared = path.join(os.homedir(), ".config", "secrets", "myapps.env"); +if (fs.existsSync(shared)) { + dotenv.config({ path: shared, override: false }); +} + +// 2) Let dotenv-flow load the standard cascade for the project: +// .env -> .env.local -> .env.[NODE_ENV] -> .env.[NODE_ENV].local +dotenvFlow.config({ + node_env: process.env.NODE_ENV, // e.g. "development", "test", "production" + silent: true, // don’t log missing files +}); \ No newline at end of file diff --git a/typescript/rag/app.ts b/typescript/rag/app.ts index bdc2c5ef..25ee948c 100644 --- a/typescript/rag/app.ts +++ b/typescript/rag/app.ts @@ -1,4 +1,4 @@ -import * as dotenv from 'dotenv'; +import "./src/config/env"; // side-effect: loads env vars import { OpenAI } from 'openai'; import { log, wrapOpenAI, init, flush } from 'galileo'; import chalk from 'chalk'; diff --git a/typescript/rag/src/config/env.ts b/typescript/rag/src/config/env.ts new file mode 100644 index 00000000..c94275f4 --- /dev/null +++ b/typescript/rag/src/config/env.ts @@ -0,0 +1,20 @@ +// src/config/env.ts +import fs from "node:fs"; +import path from "node:path"; +import os from "node:os"; +import dotenv from "dotenv"; +import dotenvFlow from "dotenv-flow"; + +// 1) Load a shared file FIRST (lowest precedence among files) +// Real env vars in process.env always win. +const shared = path.join(os.homedir(), ".config", "secrets", "myapps.env"); +if (fs.existsSync(shared)) { + dotenv.config({ path: shared, override: false }); +} + +// 2) Let dotenv-flow load the standard cascade for the project: +// .env -> .env.local -> .env.[NODE_ENV] -> .env.[NODE_ENV].local +dotenvFlow.config({ + node_env: process.env.NODE_ENV, // e.g. "development", "test", "production" + silent: true, // don’t log missing files +}); \ No newline at end of file