From 6b03425e8c61ba92b05cc00daf9f112f662b3086 Mon Sep 17 00:00:00 2001 From: Jiayou Chao Date: Fri, 11 Jul 2025 13:35:21 -0400 Subject: [PATCH 1/3] feat: add .env support for API keys, update docs, and add python-dotenv --- .env.sample | 14 ++++++++++++++ README.md | 12 ++++++------ requirements.txt | 2 ++ tradingagents/default_config.py | 4 ++++ 4 files changed, 26 insertions(+), 6 deletions(-) create mode 100644 .env.sample diff --git a/.env.sample b/.env.sample new file mode 100644 index 00000000..5337de10 --- /dev/null +++ b/.env.sample @@ -0,0 +1,14 @@ +# Finnhub API Key +FINNHUB_API_KEY="YOUR_FINNHUB_API_KEY" + +# OpenAI API Key +OPENAI_API_KEY="YOUR_OPENAI_API_KEY" + +# Data directory +DATA_DIR="/Users/yluo/Documents/Code/ScAI/FR1-data" + +# LLM settings +LLM_PROVIDER="openai" +DEEP_THINK_LLM="o4-mini" +QUICK_THINK_LLM="gpt-4o-mini" +BACKEND_URL="https://api.openai.com/v1" \ No newline at end of file diff --git a/README.md b/README.md index cac18691..8bb7039e 100644 --- a/README.md +++ b/README.md @@ -114,15 +114,15 @@ pip install -r requirements.txt ### Required APIs -You will also need the FinnHub API for financial data. All of our code is implemented with the free tier. +You will need API keys from FinnHub and OpenAI. You can provide them by creating a `.env` file in the root of the project. Rename the `.env.sample` file to `.env` and add your API keys: + ```bash -export FINNHUB_API_KEY=$YOUR_FINNHUB_API_KEY +# .env +FINNHUB_API_KEY="YOUR_FINNHUB_API_KEY" +OPENAI_API_KEY="YOUR_OPENAI_API_KEY" ``` -You will need the OpenAI API for all the agents. -```bash -export OPENAI_API_KEY=$YOUR_OPENAI_API_KEY -``` +The application will automatically load these keys. Alternatively, you can still use environment variables if you prefer. ### CLI Usage diff --git a/requirements.txt b/requirements.txt index a6154cd2..f57b352f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -24,3 +24,5 @@ rich questionary langchain_anthropic langchain-google-genai + +python-dotenv diff --git a/tradingagents/default_config.py b/tradingagents/default_config.py index 089e9c24..b443318c 100644 --- a/tradingagents/default_config.py +++ b/tradingagents/default_config.py @@ -1,4 +1,8 @@ import os +from dotenv import load_dotenv + +# Load environment variables from .env file +load_dotenv() DEFAULT_CONFIG = { "project_dir": os.path.abspath(os.path.join(os.path.dirname(__file__), ".")), From e3368c6b8715dd33e8da1bf756b05f60ea69ed8e Mon Sep 17 00:00:00 2001 From: Jiayou Chao Date: Fri, 11 Jul 2025 17:43:15 -0400 Subject: [PATCH 2/3] fix: ensure OpenAI backend URL is used from environment or config --- .env.sample | 8 -------- .gitignore | 2 ++ cli/main.py | 2 ++ tradingagents/agents/utils/memory.py | 8 ++++++-- tradingagents/default_config.py | 2 +- tradingagents/graph/trading_graph.py | 6 ++++++ 6 files changed, 17 insertions(+), 11 deletions(-) diff --git a/.env.sample b/.env.sample index 5337de10..f3b5792f 100644 --- a/.env.sample +++ b/.env.sample @@ -3,12 +3,4 @@ FINNHUB_API_KEY="YOUR_FINNHUB_API_KEY" # OpenAI API Key OPENAI_API_KEY="YOUR_OPENAI_API_KEY" - -# Data directory -DATA_DIR="/Users/yluo/Documents/Code/ScAI/FR1-data" - -# LLM settings -LLM_PROVIDER="openai" -DEEP_THINK_LLM="o4-mini" -QUICK_THINK_LLM="gpt-4o-mini" BACKEND_URL="https://api.openai.com/v1" \ No newline at end of file diff --git a/.gitignore b/.gitignore index 4ebf99e3..c3c6254e 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ eval_results/ eval_data/ *.egg-info/ .env +.vscode/ +results/ diff --git a/cli/main.py b/cli/main.py index 64616ee1..81b2dc7a 100644 --- a/cli/main.py +++ b/cli/main.py @@ -20,6 +20,8 @@ from rich import box from rich.align import Align from rich.rule import Rule +from dotenv import load_dotenv +load_dotenv() from tradingagents.graph.trading_graph import TradingAgentsGraph from tradingagents.default_config import DEFAULT_CONFIG from cli.models import AnalystType diff --git a/tradingagents/agents/utils/memory.py b/tradingagents/agents/utils/memory.py index 69b8ab8c..e9315ab4 100644 --- a/tradingagents/agents/utils/memory.py +++ b/tradingagents/agents/utils/memory.py @@ -1,3 +1,4 @@ +import os import chromadb from chromadb.config import Settings from openai import OpenAI @@ -5,11 +6,14 @@ from openai import OpenAI class FinancialSituationMemory: def __init__(self, name, config): - if config["backend_url"] == "http://localhost:11434/v1": + backend_url = os.environ.get("BACKEND_URL", config.get("backend_url")) + api_key = os.environ.get("OPENAI_API_KEY", config.get("openai_api_key")) + + if backend_url == "http://localhost:11434/v1": self.embedding = "nomic-embed-text" else: self.embedding = "text-embedding-3-small" - self.client = OpenAI(base_url=config["backend_url"]) + self.client = OpenAI(base_url=backend_url, api_key=api_key) self.chroma_client = chromadb.Client(Settings(allow_reset=True)) self.situation_collection = self.chroma_client.create_collection(name=name) diff --git a/tradingagents/default_config.py b/tradingagents/default_config.py index b443318c..ddd85965 100644 --- a/tradingagents/default_config.py +++ b/tradingagents/default_config.py @@ -16,7 +16,7 @@ DEFAULT_CONFIG = { "llm_provider": "openai", "deep_think_llm": "o4-mini", "quick_think_llm": "gpt-4o-mini", - "backend_url": "https://api.openai.com/v1", + "backend_url": os.getenv("BACKEND_URL", "https://api.openai.com/v1"), # Debate and discussion settings "max_debate_rounds": 1, "max_risk_discuss_rounds": 1, diff --git a/tradingagents/graph/trading_graph.py b/tradingagents/graph/trading_graph.py index 80a29e53..1b890716 100644 --- a/tradingagents/graph/trading_graph.py +++ b/tradingagents/graph/trading_graph.py @@ -48,6 +48,12 @@ class TradingAgentsGraph: self.debug = debug self.config = config or DEFAULT_CONFIG + # Override config with environment variables if set + self.config["backend_url"] = os.environ.get("BACKEND_URL", self.config.get("backend_url")) + self.config["OPENAI_API_KEY"] = os.environ.get("OPENAI_API_KEY", self.config.get("OPENAI_API_KEY")) + self.config["deep_think_llm"] = os.environ.get("DEEP_THINK_LLM", self.config.get("deep_think_llm")) + self.config["quick_think_llm"] = os.environ.get("QUICK_THINK_LLM", self.config.get("quick_think_llm")) + # Update the interface's config set_config(self.config) From de9891472417919ef4b6ff8716654e6e77d9d1fd Mon Sep 17 00:00:00 2001 From: Jiayou Chao Date: Fri, 25 Jul 2025 19:14:07 -0400 Subject: [PATCH 3/3] fix: add UTF-8 encoding to file operations to avoid UnicodeEncodeError. The issue is that files are being opened without specifying a character encoding, causing Python to fall back to the system default, which may not handle certain Unicode characters. --- cli/main.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cli/main.py b/cli/main.py index 81b2dc7a..fe575dae 100644 --- a/cli/main.py +++ b/cli/main.py @@ -396,7 +396,7 @@ def update_display(layout, spinner_text=None): def get_user_selections(): """Get all user selections before starting the analysis display.""" # Display ASCII art welcome message - with open("./cli/static/welcome.txt", "r") as f: + with open("./cli/static/welcome.txt", "r", encoding="utf-8") as f: welcome_ascii = f.read() # Create welcome box content @@ -766,7 +766,7 @@ def run_analysis(): func(*args, **kwargs) timestamp, message_type, content = obj.messages[-1] content = content.replace("\n", " ") # Replace newlines with spaces - with open(log_file, "a") as f: + with open(log_file, "a", encoding="utf-8") as f: f.write(f"{timestamp} [{message_type}] {content}\n") return wrapper @@ -777,7 +777,7 @@ def run_analysis(): func(*args, **kwargs) timestamp, tool_name, args = obj.tool_calls[-1] args_str = ", ".join(f"{k}={v}" for k, v in args.items()) - with open(log_file, "a") as f: + with open(log_file, "a", encoding="utf-8") as f: f.write(f"{timestamp} [Tool Call] {tool_name}({args_str})\n") return wrapper @@ -790,7 +790,7 @@ def run_analysis(): content = obj.report_sections[section_name] if content: file_name = f"{section_name}.md" - with open(report_dir / file_name, "w") as f: + with open(report_dir / file_name, "w", encoding="utf-8") as f: f.write(content) return wrapper