From 0cfe88e2ea119cca3f92883cbdb76fde4c666c3f Mon Sep 17 00:00:00 2001 From: fengfeng Date: Wed, 9 Jul 2025 21:29:58 +0800 Subject: [PATCH] added deepseek to the list of agents --- .gitignore | 1 + README.md | 8 +++--- cli/utils.py | 19 ++++++++++---- main.py | 12 ++++++--- requirements.txt | 6 ++++- tradingagents/agents/utils/memory.py | 37 +++++++++++++++++++--------- tradingagents/default_config.py | 13 ++++++---- tradingagents/graph/trading_graph.py | 7 +++++- 8 files changed, 72 insertions(+), 31 deletions(-) diff --git a/.gitignore b/.gitignore index 8313619e..1506771c 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ src/ eval_results/ eval_data/ *.egg-info/ +.env \ No newline at end of file diff --git a/README.md b/README.md index cac18691..b4be50e1 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,7 @@ cd TradingAgents Create a virtual environment in any of your favorite environment managers: ```bash -conda create -n tradingagents python=3.13 +conda create -n tradingagents python=3.11 conda activate tradingagents ``` @@ -119,9 +119,9 @@ You will also need the FinnHub API for financial data. All of our code is implem export FINNHUB_API_KEY=$YOUR_FINNHUB_API_KEY ``` -You will need the OpenAI API for all the agents. +You will need the DeepSeek API for all the agents. By default, TradingAgents uses DeepSeek as the LLM provider. ```bash -export OPENAI_API_KEY=$YOUR_OPENAI_API_KEY +export DEEPSEEK_API_KEY=$YOUR_DEEPSEEK_API_KEY ``` ### CLI Usage @@ -150,7 +150,7 @@ An interface will appear showing results as they load, letting you track the age ### Implementation Details -We built TradingAgents with LangGraph to ensure flexibility and modularity. We utilize `o1-preview` and `gpt-4o` as our deep thinking and fast thinking LLMs for our experiments. However, for testing purposes, we recommend you use `o4-mini` and `gpt-4.1-mini` to save on costs as our framework makes **lots of** API calls. +We built TradingAgents with LangGraph to ensure flexibility and modularity. By default, we utilize `deepseek-chat` as our deep thinking and fast thinking LLMs. You can change the default models in `tradingagents/default_config.py`. ### Python Usage diff --git a/cli/utils.py b/cli/utils.py index d3873360..ea14c832 100644 --- a/cli/utils.py +++ b/cli/utils.py @@ -144,6 +144,10 @@ def select_shallow_thinking_agent(provider) -> str: ("Gemini 2.0 Flash - Next generation features, speed, and thinking", "gemini-2.0-flash"), ("Gemini 2.5 Flash - Adaptive thinking, cost efficiency", "gemini-2.5-flash-preview-05-20"), ], + "deepseek": [ + ("DeepSeek Chat - Fast and efficient chat model", "deepseek-chat"), + ("DeepSeek Reasoner - Advanced reasoning model", "deepseek-reasoner"), + ], "openrouter": [ ("Meta: Llama 4 Scout", "meta-llama/llama-4-scout:free"), ("Meta: Llama 3.3 8B Instruct - A lightweight and ultra-fast variant of Llama 3.3 70B", "meta-llama/llama-3.3-8b-instruct:free"), @@ -198,7 +202,7 @@ def select_deep_thinking_agent(provider) -> str: ("Claude Sonnet 3.5 - Highly capable standard model", "claude-3-5-sonnet-latest"), ("Claude Sonnet 3.7 - Exceptional hybrid reasoning and agentic capabilities", "claude-3-7-sonnet-latest"), ("Claude Sonnet 4 - High performance and excellent reasoning", "claude-sonnet-4-0"), - ("Claude Opus 4 - Most powerful Anthropic model", " claude-opus-4-0"), + ("Claude Opus 4 - Most powerful Anthropic model", "\tclaude-opus-4-0"), ], "google": [ ("Gemini 2.0 Flash-Lite - Cost efficiency and low latency", "gemini-2.0-flash-lite"), @@ -206,6 +210,10 @@ def select_deep_thinking_agent(provider) -> str: ("Gemini 2.5 Flash - Adaptive thinking, cost efficiency", "gemini-2.5-flash-preview-05-20"), ("Gemini 2.5 Pro", "gemini-2.5-pro-preview-06-05"), ], + "deepseek": [ + ("DeepSeek Chat - Fast and efficient chat model", "deepseek-chat"), + ("DeepSeek Reasoner - Advanced reasoning model", "deepseek-reasoner"), + ], "openrouter": [ ("DeepSeek V3 - a 685B-parameter, mixture-of-experts model", "deepseek/deepseek-chat-v3-0324:free"), ("Deepseek - latest iteration of the flagship chat model family from the DeepSeek team.", "deepseek/deepseek-chat-v3-0324:free"), @@ -238,12 +246,13 @@ def select_deep_thinking_agent(provider) -> str: return choice def select_llm_provider() -> tuple[str, str]: - """Select the OpenAI api url using interactive selection.""" - # Define OpenAI api options with their corresponding endpoints + """Select the LLM provider using interactive selection.""" + # Define LLM provider options with their corresponding endpoints BASE_URLS = [ ("OpenAI", "https://api.openai.com/v1"), ("Anthropic", "https://api.anthropic.com/"), ("Google", "https://generativelanguage.googleapis.com/v1"), + ("DeepSeek", "https://api.deepseek.com"), ("Openrouter", "https://openrouter.ai/api/v1"), ("Ollama", "http://localhost:11434/v1"), ] @@ -265,10 +274,10 @@ def select_llm_provider() -> tuple[str, str]: ).ask() if choice is None: - console.print("\n[red]no OpenAI backend selected. Exiting...[/red]") + console.print("\n[red]no LLM provider selected. Exiting...[/red]") exit(1) display_name, url = choice print(f"You selected: {display_name}\tURL: {url}") - return display_name, url + return display_name, url \ No newline at end of file diff --git a/main.py b/main.py index 6c8ae3d9..2e9e8664 100644 --- a/main.py +++ b/main.py @@ -1,12 +1,16 @@ +from dotenv import load_dotenv + +load_dotenv() + from tradingagents.graph.trading_graph import TradingAgentsGraph from tradingagents.default_config import DEFAULT_CONFIG # Create a custom config config = DEFAULT_CONFIG.copy() -config["llm_provider"] = "google" # Use a different model -config["backend_url"] = "https://generativelanguage.googleapis.com/v1" # Use a different backend -config["deep_think_llm"] = "gemini-2.0-flash" # Use a different model -config["quick_think_llm"] = "gemini-2.0-flash" # Use a different model +config["llm_provider"] = "deepseek" # Use a different model +config["backend_url"] = "https://api.deepseek.com" # Use a different backend +config["deep_think_llm"] = "deepseek-chat" # Use a different model +config["quick_think_llm"] = "deepseek-chat" # Use a different model config["max_debate_rounds"] = 1 # Increase debate rounds config["online_tools"] = True # Increase debate rounds diff --git a/requirements.txt b/requirements.txt index 1c7c2818..f9bd9b91 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,8 @@ typing-extensions langchain-openai +langchain-anthropic +langchain-google-genai +langchain-deepseek langchain-experimental pandas yfinance @@ -21,4 +24,5 @@ pytz redis chainlit rich -questionary +typer +questionary \ No newline at end of file diff --git a/tradingagents/agents/utils/memory.py b/tradingagents/agents/utils/memory.py index f3415765..b4cdb736 100644 --- a/tradingagents/agents/utils/memory.py +++ b/tradingagents/agents/utils/memory.py @@ -1,25 +1,40 @@ import chromadb from chromadb.config import Settings from openai import OpenAI +import os +from sentence_transformers import SentenceTransformer class FinancialSituationMemory: def __init__(self, name, config): - if config["backend_url"] == "http://localhost:11434/v1": - self.embedding = "nomic-embed-text" + if config["llm_provider"].lower() == "deepseek": + self.embedding_model = SentenceTransformer('all-MiniLM-L6-v2') else: - self.embedding = "text-embedding-3-small" - self.client = OpenAI() + if config["backend_url"] == "http://localhost:11434/v1": + self.embedding = "nomic-embed-text" + else: + self.embedding = "text-embedding-3-small" + + if config["llm_provider"].lower() == "deepseek": + self.client = OpenAI( + api_key=os.getenv("DEEPSEEK_API_KEY"), + base_url=config["backend_url"] + ) + else: + self.client = OpenAI() + self.chroma_client = chromadb.Client(Settings(allow_reset=True)) self.situation_collection = self.chroma_client.create_collection(name=name) def get_embedding(self, text): - """Get OpenAI embedding for a text""" - - response = self.client.embeddings.create( - model=self.embedding, input=text - ) - return response.data[0].embedding + """Get embedding for a text""" + if hasattr(self, 'embedding_model'): + return self.embedding_model.encode(text).tolist() + else: + response = self.client.embeddings.create( + model=self.embedding, input=text + ) + return response.data[0].embedding def add_situations(self, situations_and_advice): """Add financial situations and their corresponding advice. Parameter is a list of tuples (situation, rec)""" @@ -110,4 +125,4 @@ if __name__ == "__main__": print(f"Recommendation: {rec['recommendation']}") except Exception as e: - print(f"Error during recommendation: {str(e)}") + print(f"Error during recommendation: {str(e)}") \ No newline at end of file diff --git a/tradingagents/default_config.py b/tradingagents/default_config.py index 2cf15b85..b4841ef3 100644 --- a/tradingagents/default_config.py +++ b/tradingagents/default_config.py @@ -2,16 +2,19 @@ import os DEFAULT_CONFIG = { "project_dir": os.path.abspath(os.path.join(os.path.dirname(__file__), ".")), - "data_dir": "/Users/yluo/Documents/Code/ScAI/FR1-data", + "data_dir": os.path.join( + os.path.abspath(os.path.join(os.path.dirname(__file__), ".")), + "dataflows/data_cache", + ), "data_cache_dir": os.path.join( os.path.abspath(os.path.join(os.path.dirname(__file__), ".")), "dataflows/data_cache", ), # LLM settings - "llm_provider": "openai", - "deep_think_llm": "o4-mini", - "quick_think_llm": "gpt-4o-mini", - "backend_url": "https://api.openai.com/v1", + "llm_provider": "deepseek", + "deep_think_llm": "deepseek-chat", + "quick_think_llm": "deepseek-chat", + "backend_url": "https://api.deepseek.com", # 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 eb06cf43..8f43aaf9 100644 --- a/tradingagents/graph/trading_graph.py +++ b/tradingagents/graph/trading_graph.py @@ -9,6 +9,7 @@ from typing import Dict, Any, Tuple, List, Optional from langchain_openai import ChatOpenAI from langchain_anthropic import ChatAnthropic from langchain_google_genai import ChatGoogleGenerativeAI +from langchain_deepseek import ChatDeepSeek from langgraph.prebuilt import ToolNode @@ -67,6 +68,10 @@ class TradingAgentsGraph: elif self.config["llm_provider"].lower() == "google": self.deep_thinking_llm = ChatGoogleGenerativeAI(model=self.config["deep_think_llm"]) self.quick_thinking_llm = ChatGoogleGenerativeAI(model=self.config["quick_think_llm"]) + elif self.config["llm_provider"].lower() == "deepseek": + deepseek_api_key = os.getenv("DEEPSEEK_API_KEY") + self.deep_thinking_llm = ChatDeepSeek(model=self.config["deep_think_llm"], base_url=self.config["backend_url"], api_key=deepseek_api_key) + self.quick_thinking_llm = ChatDeepSeek(model=self.config["quick_think_llm"], base_url=self.config["backend_url"], api_key=deepseek_api_key) else: raise ValueError(f"Unsupported LLM provider: {self.config['llm_provider']}") @@ -251,4 +256,4 @@ class TradingAgentsGraph: def process_signal(self, full_signal): """Process a signal to extract the core decision.""" - return self.signal_processor.process_signal(full_signal) + return self.signal_processor.process_signal(full_signal) \ No newline at end of file