mirror of
https://gitee.com/wanwujie/deer-flow
synced 2026-04-26 07:14:47 +08:00
Upgrade langchain version to 1.x (#720)
* fix: revert the part of patch of issue-710 to extract the content from the plan * Upgrade the ddgs for the new compatible version * Upgraded langchain to 1.1.0 updated langchain related package to the new compatable version * Update pyproject.toml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -318,6 +318,12 @@ curl --location 'http://localhost:8000/api/tts' \
|
|||||||
## Development
|
## Development
|
||||||
|
|
||||||
### Testing
|
### Testing
|
||||||
|
Install development dependencies:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uv pip install -e ".[test]"
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
Run the test suite:
|
Run the test suite:
|
||||||
|
|
||||||
|
|||||||
@@ -10,10 +10,16 @@ readme = "README.md"
|
|||||||
requires-python = ">=3.12"
|
requires-python = ">=3.12"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"httpx>=0.28.1",
|
"httpx>=0.28.1",
|
||||||
|
# LangChain 1.x core packages
|
||||||
|
"langchain>=1.0.0",
|
||||||
|
"langchain-core>=1.0.0",
|
||||||
"langchain-community>=0.3.19",
|
"langchain-community>=0.3.19",
|
||||||
"langchain-experimental>=0.3.4",
|
"langchain-experimental>=0.3.4",
|
||||||
"langchain-openai>=0.3.8",
|
"langchain-openai>=0.3.8",
|
||||||
|
"langchain-text-splitters>=0.3.6",
|
||||||
|
# LangGraph
|
||||||
"langgraph>=0.3.5",
|
"langgraph>=0.3.5",
|
||||||
|
# Other dependencies
|
||||||
"readabilipy>=0.3.0",
|
"readabilipy>=0.3.0",
|
||||||
"python-dotenv>=1.0.1",
|
"python-dotenv>=1.0.1",
|
||||||
"socksio>=1.0.0",
|
"socksio>=1.0.0",
|
||||||
@@ -28,6 +34,7 @@ dependencies = [
|
|||||||
"json-repair>=0.7.0",
|
"json-repair>=0.7.0",
|
||||||
"jinja2>=3.1.3",
|
"jinja2>=3.1.3",
|
||||||
"duckduckgo-search>=8.0.0",
|
"duckduckgo-search>=8.0.0",
|
||||||
|
"ddgs>=9.0.0",
|
||||||
"inquirerpy>=0.3.4",
|
"inquirerpy>=0.3.4",
|
||||||
"arxiv>=2.2.0",
|
"arxiv>=2.2.0",
|
||||||
"mcp>=1.11.0",
|
"mcp>=1.11.0",
|
||||||
@@ -35,14 +42,14 @@ dependencies = [
|
|||||||
"langchain-deepseek>=0.1.3",
|
"langchain-deepseek>=0.1.3",
|
||||||
"langchain-google-genai>=2.0.6",
|
"langchain-google-genai>=2.0.6",
|
||||||
"wikipedia>=1.4.0",
|
"wikipedia>=1.4.0",
|
||||||
"langchain-tavily<0.3",
|
"langchain-tavily>=0.2.0",
|
||||||
"langgraph-checkpoint-mongodb>=0.1.4",
|
"langgraph-checkpoint-mongodb>=0.1.4",
|
||||||
"langgraph-checkpoint-postgres==2.0.21",
|
"langgraph-checkpoint-postgres==2.0.21",
|
||||||
"pymilvus>=2.3.0",
|
"pymilvus>=2.3.0",
|
||||||
"langchain-milvus>=0.2.1",
|
"langchain-milvus>=0.2.1",
|
||||||
"psycopg[binary]>=3.2.9",
|
"psycopg[binary]>=3.2.9",
|
||||||
"qdrant-client>=1.15.1",
|
"qdrant-client>=1.15.1",
|
||||||
"langchain-qdrant>=0.2.0,<1.0.0",
|
"langchain-qdrant>=0.2.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from langchain.schema import HumanMessage, SystemMessage
|
from langchain_core.messages import HumanMessage, SystemMessage
|
||||||
|
|
||||||
from src.config.agents import AGENT_LLM_MAP
|
from src.config.agents import AGENT_LLM_MAP
|
||||||
from src.llms.llm import get_llm_by_type
|
from src.llms.llm import get_llm_by_type
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import logging
|
|||||||
import os
|
import os
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from langchain.schema import HumanMessage, SystemMessage
|
from langchain_core.messages import HumanMessage, SystemMessage
|
||||||
|
|
||||||
from src.config.agents import AGENT_LLM_MAP
|
from src.config.agents import AGENT_LLM_MAP
|
||||||
from src.llms.llm import get_llm_by_type
|
from src.llms.llm import get_llm_by_type
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from langchain.schema import HumanMessage
|
from langchain_core.messages import HumanMessage
|
||||||
|
|
||||||
from src.config.agents import AGENT_LLM_MAP
|
from src.config.agents import AGENT_LLM_MAP
|
||||||
from src.llms.llm import get_llm_by_type
|
from src.llms.llm import get_llm_by_type
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from langchain.schema import HumanMessage, SystemMessage
|
from langchain_core.messages import HumanMessage, SystemMessage
|
||||||
|
|
||||||
from src.config.agents import AGENT_LLM_MAP
|
from src.config.agents import AGENT_LLM_MAP
|
||||||
from src.llms.llm import get_llm_by_type
|
from src.llms.llm import get_llm_by_type
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from langchain.schema import HumanMessage, SystemMessage
|
from langchain_core.messages import HumanMessage, SystemMessage
|
||||||
|
|
||||||
from src.config.agents import AGENT_LLM_MAP
|
from src.config.agents import AGENT_LLM_MAP
|
||||||
from src.llms.llm import get_llm_by_type
|
from src.llms.llm import get_llm_by_type
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from langchain.schema import HumanMessage, SystemMessage
|
from langchain_core.messages import HumanMessage, SystemMessage
|
||||||
|
|
||||||
from src.config.agents import AGENT_LLM_MAP
|
from src.config.agents import AGENT_LLM_MAP
|
||||||
from src.llms.llm import get_llm_by_type
|
from src.llms.llm import get_llm_by_type
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from langchain.schema import HumanMessage, SystemMessage
|
from langchain_core.messages import HumanMessage, SystemMessage
|
||||||
|
|
||||||
from src.config.agents import AGENT_LLM_MAP
|
from src.config.agents import AGENT_LLM_MAP
|
||||||
from src.llms.llm import get_llm_by_type
|
from src.llms.llm import get_llm_by_type
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from langchain.schema import HumanMessage, SystemMessage
|
from langchain_core.messages import HumanMessage, SystemMessage
|
||||||
|
|
||||||
from src.config.agents import AGENT_LLM_MAP
|
from src.config.agents import AGENT_LLM_MAP
|
||||||
from src.llms.llm import get_llm_by_type
|
from src.llms.llm import get_llm_by_type
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from langchain.schema import HumanMessage, SystemMessage
|
from langchain_core.messages import HumanMessage, SystemMessage
|
||||||
|
|
||||||
from src.config.agents import AGENT_LLM_MAP
|
from src.config.agents import AGENT_LLM_MAP
|
||||||
from src.llms.llm import get_llm_by_type
|
from src.llms.llm import get_llm_by_type
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import json
|
|||||||
import logging
|
import logging
|
||||||
from typing import Dict, List, Optional, Tuple, Union
|
from typing import Dict, List, Optional, Tuple, Union
|
||||||
|
|
||||||
from langchain.callbacks.manager import (
|
from langchain_core.callbacks import (
|
||||||
AsyncCallbackManagerForToolRun,
|
AsyncCallbackManagerForToolRun,
|
||||||
CallbackManagerForToolRun,
|
CallbackManagerForToolRun,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from langchain.schema import HumanMessage, SystemMessage
|
from langchain_core.messages import HumanMessage, SystemMessage
|
||||||
|
|
||||||
from src.config.report_style import ReportStyle
|
from src.config.report_style import ReportStyle
|
||||||
from src.prompt_enhancer.graph.enhancer_node import prompt_enhancer_node
|
from src.prompt_enhancer.graph.enhancer_node import prompt_enhancer_node
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ class TestCrawlTool:
|
|||||||
url = "https://example.com"
|
url = "https://example.com"
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
result = crawl_tool(url)
|
result = crawl_tool.invoke({"url": url})
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
assert isinstance(result, str)
|
assert isinstance(result, str)
|
||||||
@@ -44,7 +44,7 @@ class TestCrawlTool:
|
|||||||
url = "https://example.com"
|
url = "https://example.com"
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
result = crawl_tool(url)
|
result = crawl_tool.invoke({"url": url})
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
result_dict = json.loads(result)
|
result_dict = json.loads(result)
|
||||||
@@ -61,7 +61,7 @@ class TestCrawlTool:
|
|||||||
url = "https://example.com"
|
url = "https://example.com"
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
result = crawl_tool(url)
|
result = crawl_tool.invoke({"url": url})
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
assert isinstance(result, str)
|
assert isinstance(result, str)
|
||||||
@@ -80,7 +80,7 @@ class TestCrawlTool:
|
|||||||
url = "https://example.com"
|
url = "https://example.com"
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
result = crawl_tool(url)
|
result = crawl_tool.invoke({"url": url})
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
assert isinstance(result, str)
|
assert isinstance(result, str)
|
||||||
@@ -103,7 +103,7 @@ class TestCrawlTool:
|
|||||||
url = "https://example.com"
|
url = "https://example.com"
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
result = crawl_tool(url)
|
result = crawl_tool.invoke({"url": url})
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
assert isinstance(result, str)
|
assert isinstance(result, str)
|
||||||
@@ -123,7 +123,7 @@ class TestCrawlTool:
|
|||||||
url = "https://example.com"
|
url = "https://example.com"
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
result = crawl_tool(url)
|
result = crawl_tool.invoke({"url": url})
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
assert isinstance(result, str)
|
assert isinstance(result, str)
|
||||||
@@ -171,7 +171,7 @@ class TestPDFHandling:
|
|||||||
pdf_url = "https://example.com/document.pdf"
|
pdf_url = "https://example.com/document.pdf"
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
result = crawl_tool(pdf_url)
|
result = crawl_tool.invoke({"url": pdf_url})
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
assert isinstance(result, str)
|
assert isinstance(result, str)
|
||||||
@@ -189,7 +189,7 @@ class TestPDFHandling:
|
|||||||
issue_pdf_url = "https://pdf.dfcfw.com/pdf/H3_AP202503071644153386_1.pdf"
|
issue_pdf_url = "https://pdf.dfcfw.com/pdf/H3_AP202503071644153386_1.pdf"
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
result = crawl_tool(issue_pdf_url)
|
result = crawl_tool.invoke({"url": issue_pdf_url})
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
result_dict = json.loads(result)
|
result_dict = json.loads(result)
|
||||||
@@ -204,7 +204,7 @@ class TestPDFHandling:
|
|||||||
pdf_url = "https://example.com/document.pdf"
|
pdf_url = "https://example.com/document.pdf"
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
result = crawl_tool(pdf_url)
|
result = crawl_tool.invoke({"url": pdf_url})
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
# Crawler should not be instantiated for PDF URLs
|
# Crawler should not be instantiated for PDF URLs
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class TestPythonReplTool:
|
|||||||
mock_repl.run.return_value = expected_output
|
mock_repl.run.return_value = expected_output
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
result = python_repl_tool(code)
|
result = python_repl_tool.invoke({"code": code})
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
mock_repl.run.assert_called_once_with(code)
|
mock_repl.run.assert_called_once_with(code)
|
||||||
@@ -38,7 +38,7 @@ class TestPythonReplTool:
|
|||||||
|
|
||||||
# Act & Assert - expect ValidationError when passing invalid input
|
# Act & Assert - expect ValidationError when passing invalid input
|
||||||
with pytest.raises(Exception): # Could be ValidationError or similar
|
with pytest.raises(Exception): # Could be ValidationError or similar
|
||||||
python_repl_tool(invalid_code)
|
python_repl_tool.invoke({"code": invalid_code})
|
||||||
|
|
||||||
mock_repl.run.assert_not_called()
|
mock_repl.run.assert_not_called()
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@ class TestPythonReplTool:
|
|||||||
mock_repl.run.return_value = error_result
|
mock_repl.run.return_value = error_result
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
result = python_repl_tool(code)
|
result = python_repl_tool.invoke({"code": code})
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
mock_repl.run.assert_called_once_with(code)
|
mock_repl.run.assert_called_once_with(code)
|
||||||
@@ -71,7 +71,7 @@ class TestPythonReplTool:
|
|||||||
mock_repl.run.return_value = exception_result
|
mock_repl.run.return_value = exception_result
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
result = python_repl_tool(code)
|
result = python_repl_tool.invoke({"code": code})
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
mock_repl.run.assert_called_once_with(code)
|
mock_repl.run.assert_called_once_with(code)
|
||||||
@@ -90,7 +90,7 @@ class TestPythonReplTool:
|
|||||||
mock_repl.run.side_effect = exception
|
mock_repl.run.side_effect = exception
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
result = python_repl_tool(code)
|
result = python_repl_tool.invoke({"code": code})
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
mock_repl.run.assert_called_once_with(code)
|
mock_repl.run.assert_called_once_with(code)
|
||||||
@@ -109,7 +109,7 @@ class TestPythonReplTool:
|
|||||||
mock_repl.run.return_value = expected_output
|
mock_repl.run.return_value = expected_output
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
result = python_repl_tool(code)
|
result = python_repl_tool.invoke({"code": code})
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
mock_repl.run.assert_called_once_with(code)
|
mock_repl.run.assert_called_once_with(code)
|
||||||
@@ -128,7 +128,7 @@ class TestPythonReplTool:
|
|||||||
mock_repl.run.return_value = ""
|
mock_repl.run.return_value = ""
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
result = python_repl_tool(code)
|
result = python_repl_tool.invoke({"code": code})
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
mock_repl.run.assert_called_once_with(code)
|
mock_repl.run.assert_called_once_with(code)
|
||||||
@@ -144,7 +144,7 @@ class TestPythonReplTool:
|
|||||||
mock_repl.run.return_value = ""
|
mock_repl.run.return_value = ""
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
python_repl_tool(code)
|
python_repl_tool.invoke({"code": code})
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
mock_logger.info.assert_any_call("Executing Python code")
|
mock_logger.info.assert_any_call("Executing Python code")
|
||||||
@@ -158,7 +158,7 @@ class TestPythonReplTool:
|
|||||||
code = "print('test')"
|
code = "print('test')"
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
result = python_repl_tool(code)
|
result = python_repl_tool.invoke({"code": code})
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
mock_logger.warning.assert_called_with(
|
mock_logger.warning.assert_called_with(
|
||||||
@@ -176,7 +176,7 @@ class TestPythonReplTool:
|
|||||||
code = "print('test')"
|
code = "print('test')"
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
result = python_repl_tool(code)
|
result = python_repl_tool.invoke({"code": code})
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
mock_logger.warning.assert_called_with(
|
mock_logger.warning.assert_called_with(
|
||||||
@@ -197,7 +197,7 @@ class TestPythonReplTool:
|
|||||||
mock_repl.run.return_value = expected_output
|
mock_repl.run.return_value = expected_output
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
result = python_repl_tool(code)
|
result = python_repl_tool.invoke({"code": code})
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
mock_repl.run.assert_called_once_with(code)
|
mock_repl.run.assert_called_once_with(code)
|
||||||
@@ -213,7 +213,7 @@ class TestPythonReplTool:
|
|||||||
code = "print('disabled')"
|
code = "print('disabled')"
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
result = python_repl_tool(code)
|
result = python_repl_tool.invoke({"code": code})
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
mock_logger.warning.assert_called_with(
|
mock_logger.warning.assert_called_with(
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class TestGetWebSearchTool:
|
|||||||
def test_get_web_search_tool_brave(self):
|
def test_get_web_search_tool_brave(self):
|
||||||
tool = get_web_search_tool(max_search_results=4)
|
tool = get_web_search_tool(max_search_results=4)
|
||||||
assert tool.name == "web_search"
|
assert tool.name == "web_search"
|
||||||
assert tool.search_wrapper.api_key == "test_api_key"
|
assert tool.search_wrapper.api_key.get_secret_value() == "test_api_key"
|
||||||
|
|
||||||
@patch("src.tools.search.SELECTED_SEARCH_ENGINE", SearchEngine.ARXIV.value)
|
@patch("src.tools.search.SELECTED_SEARCH_ENGINE", SearchEngine.ARXIV.value)
|
||||||
def test_get_web_search_tool_arxiv(self):
|
def test_get_web_search_tool_arxiv(self):
|
||||||
@@ -54,7 +54,7 @@ class TestGetWebSearchTool:
|
|||||||
@patch.dict(os.environ, {}, clear=True)
|
@patch.dict(os.environ, {}, clear=True)
|
||||||
def test_get_web_search_tool_brave_no_api_key(self):
|
def test_get_web_search_tool_brave_no_api_key(self):
|
||||||
tool = get_web_search_tool(max_search_results=1)
|
tool = get_web_search_tool(max_search_results=1)
|
||||||
assert tool.search_wrapper.api_key == ""
|
assert tool.search_wrapper.api_key.get_secret_value() == ""
|
||||||
|
|
||||||
@patch("src.tools.search.SELECTED_SEARCH_ENGINE", SearchEngine.TAVILY.value)
|
@patch("src.tools.search.SELECTED_SEARCH_ENGINE", SearchEngine.TAVILY.value)
|
||||||
@patch("src.tools.search.load_yaml_config")
|
@patch("src.tools.search.load_yaml_config")
|
||||||
|
|||||||
Reference in New Issue
Block a user