mirror of
https://gitee.com/wanwujie/deer-flow
synced 2026-04-15 11:04:44 +08:00
feat: add deep think feature (#311)
* feat: implement backend logic * feat: implement api/config endpoint * rename the symbol * feat: re-implement configuration at client-side * feat: add client-side of deep thinking * fix backend bug * feat: add reasoning block * docs: update readme * fix: translate into English * fix: change icon to lightbulb * feat: ignore more bad cases * feat: adjust thinking layout, and implement auto scrolling * docs: add comments --------- Co-authored-by: Henry Li <henry1943@163.com>
This commit is contained in:
@@ -6,6 +6,8 @@ from typing import Any, Dict
|
||||
import os
|
||||
|
||||
from langchain_openai import ChatOpenAI
|
||||
from langchain_deepseek import ChatDeepSeek
|
||||
from typing import get_args
|
||||
|
||||
from src.config import load_yaml_config
|
||||
from src.config.agents import LLMType
|
||||
@@ -14,6 +16,20 @@ from src.config.agents import LLMType
|
||||
_llm_cache: dict[LLMType, ChatOpenAI] = {}
|
||||
|
||||
|
||||
def _get_config_file_path() -> str:
|
||||
"""Get the path to the configuration file."""
|
||||
return str((Path(__file__).parent.parent.parent / "conf.yaml").resolve())
|
||||
|
||||
|
||||
def _get_llm_type_config_keys() -> dict[str, str]:
|
||||
"""Get mapping of LLM types to their configuration keys."""
|
||||
return {
|
||||
"reasoning": "REASONING_MODEL",
|
||||
"basic": "BASIC_MODEL",
|
||||
"vision": "VISION_MODEL",
|
||||
}
|
||||
|
||||
|
||||
def _get_env_llm_conf(llm_type: str) -> Dict[str, Any]:
|
||||
"""
|
||||
Get LLM configuration from environment variables.
|
||||
@@ -29,15 +45,20 @@ def _get_env_llm_conf(llm_type: str) -> Dict[str, Any]:
|
||||
return conf
|
||||
|
||||
|
||||
def _create_llm_use_conf(llm_type: LLMType, conf: Dict[str, Any]) -> ChatOpenAI:
|
||||
llm_type_map = {
|
||||
"reasoning": conf.get("REASONING_MODEL", {}),
|
||||
"basic": conf.get("BASIC_MODEL", {}),
|
||||
"vision": conf.get("VISION_MODEL", {}),
|
||||
}
|
||||
llm_conf = llm_type_map.get(llm_type)
|
||||
def _create_llm_use_conf(
|
||||
llm_type: LLMType, conf: Dict[str, Any]
|
||||
) -> ChatOpenAI | ChatDeepSeek:
|
||||
"""Create LLM instance using configuration."""
|
||||
llm_type_config_keys = _get_llm_type_config_keys()
|
||||
config_key = llm_type_config_keys.get(llm_type)
|
||||
|
||||
if not config_key:
|
||||
raise ValueError(f"Unknown LLM type: {llm_type}")
|
||||
|
||||
llm_conf = conf.get(config_key, {})
|
||||
if not isinstance(llm_conf, dict):
|
||||
raise ValueError(f"Invalid LLM Conf: {llm_type}")
|
||||
raise ValueError(f"Invalid LLM configuration for {llm_type}: {llm_conf}")
|
||||
|
||||
# Get configuration from environment variables
|
||||
env_conf = _get_env_llm_conf(llm_type)
|
||||
|
||||
@@ -45,9 +66,16 @@ def _create_llm_use_conf(llm_type: LLMType, conf: Dict[str, Any]) -> ChatOpenAI:
|
||||
merged_conf = {**llm_conf, **env_conf}
|
||||
|
||||
if not merged_conf:
|
||||
raise ValueError(f"Unknown LLM Conf: {llm_type}")
|
||||
raise ValueError(f"No configuration found for LLM type: {llm_type}")
|
||||
|
||||
return ChatOpenAI(**merged_conf)
|
||||
if llm_type == "reasoning":
|
||||
merged_conf["api_base"] = merged_conf.pop("base_url", None)
|
||||
|
||||
return (
|
||||
ChatOpenAI(**merged_conf)
|
||||
if llm_type != "reasoning"
|
||||
else ChatDeepSeek(**merged_conf)
|
||||
)
|
||||
|
||||
|
||||
def get_llm_by_type(
|
||||
@@ -59,14 +87,49 @@ def get_llm_by_type(
|
||||
if llm_type in _llm_cache:
|
||||
return _llm_cache[llm_type]
|
||||
|
||||
conf = load_yaml_config(
|
||||
str((Path(__file__).parent.parent.parent / "conf.yaml").resolve())
|
||||
)
|
||||
conf = load_yaml_config(_get_config_file_path())
|
||||
llm = _create_llm_use_conf(llm_type, conf)
|
||||
_llm_cache[llm_type] = llm
|
||||
return llm
|
||||
|
||||
|
||||
def get_configured_llm_models() -> dict[str, list[str]]:
|
||||
"""
|
||||
Get all configured LLM models grouped by type.
|
||||
|
||||
Returns:
|
||||
Dictionary mapping LLM type to list of configured model names.
|
||||
"""
|
||||
try:
|
||||
conf = load_yaml_config(_get_config_file_path())
|
||||
llm_type_config_keys = _get_llm_type_config_keys()
|
||||
|
||||
configured_models: dict[str, list[str]] = {}
|
||||
|
||||
for llm_type in get_args(LLMType):
|
||||
# Get configuration from YAML file
|
||||
config_key = llm_type_config_keys.get(llm_type, "")
|
||||
yaml_conf = conf.get(config_key, {}) if config_key else {}
|
||||
|
||||
# Get configuration from environment variables
|
||||
env_conf = _get_env_llm_conf(llm_type)
|
||||
|
||||
# Merge configurations, with environment variables taking precedence
|
||||
merged_conf = {**yaml_conf, **env_conf}
|
||||
|
||||
# Check if model is configured
|
||||
model_name = merged_conf.get("model")
|
||||
if model_name:
|
||||
configured_models.setdefault(llm_type, []).append(model_name)
|
||||
|
||||
return configured_models
|
||||
|
||||
except Exception as e:
|
||||
# Log error and return empty dict to avoid breaking the application
|
||||
print(f"Warning: Failed to load LLM configuration: {e}")
|
||||
return {}
|
||||
|
||||
|
||||
# In the future, we will use reasoning_llm and vl_llm for different purposes
|
||||
# reasoning_llm = get_llm_by_type("reasoning")
|
||||
# vl_llm = get_llm_by_type("vision")
|
||||
|
||||
Reference in New Issue
Block a user