import os from enum import Enum from dataclasses import dataclass, fields from typing import Any, Optional, Dict from pydantic import BaseModel, Field from langchain_core.language_models.chat_models import BaseChatModel from langchain_core.runnables import RunnableConfig from dataclasses import dataclass class SearchAPI(Enum): PERPLEXITY = "perplexity" TAVILY = "tavily" EXA = "exa" ARXIV = "arxiv" PUBMED = "pubmed" LINKUP = "linkup" DUCKDUCKGO = "duckduckgo" GOOGLESEARCH = "googlesearch" @dataclass(kw_only=True) class Configuration: """The configurable fields for the chatbot.""" number_of_queries: int = 2 # 每次迭代生成几个查询 planner_provider: str = "deepseek" planner_model: str = "deepseek-chat" writer_provider: str = "deepseek" writer_model: str = "deepseek-chat" search_api: SearchAPI = SearchAPI.TAVILY search_api_config: Optional[Dict[str, Any]] = None max_tokens : 4000 @classmethod def from_runnable_config( cls, config: Optional[RunnableConfig] = None ) -> "Configuration": """Create a Configuration instance from a RunnableConfig.""" configurable = ( config["configurable"] if config and "configurable" in config else {} ) values: dict[str, Any] = { f.name: os.environ.get(f.name.upper(), configurable.get(f.name)) for f in fields(cls) if f.init } return cls(**{k: v for k, v in values.items() if v}) class BaseConfiguration(BaseModel): number_of_queries: int = Field(default=2, description="每次迭代生成几个查询") planner_provider: str = Field(default="deepseek") planner_model: str = Field(default="deepseek-reasoner") writer_provider: str = Field(default="deepseek") writer_model: str = Field(default="deepseek-chat") search_api: SearchAPI = Field(default=SearchAPI.TAVILY) search_api_config: Optional[Dict[str, Any]] = Field(default=None) search_max_len: int = Field(default=20000, description="搜索结果最大字符数")