003f081a7b
* fix: support local models by making thought field optional in Plan model - Make thought field optional in Plan model to fix Pydantic validation errors with local models - Add Ollama configuration example to conf.yaml.example - Update documentation to include local model support - Improve planner prompt with better JSON format requirements Fixes local model integration issues where models like qwen3:14b would fail due to missing thought field in JSON output. * feat: Add intelligent clarification feature for research queries - Add multi-turn clarification process to refine vague research questions - Implement three-dimension clarification standard (Tech/App, Focus, Scope) - Add clarification state management in coordinator node - Update coordinator prompt with detailed clarification guidelines - Add UI settings to enable/disable clarification feature (disabled by default) - Update workflow to handle clarification rounds recursively - Add comprehensive test coverage for clarification functionality - Update documentation with clarification feature usage guide Key components: - src/graph/nodes.py: Core clarification logic and state management - src/prompts/coordinator.md: Detailed clarification guidelines - src/workflow.py: Recursive clarification handling - web/: UI settings integration - tests/: Comprehensive test coverage - docs/: Updated configuration guide * fix: Improve clarification conversation continuity - Add comprehensive conversation history to clarification context - Include previous exchanges summary in system messages - Add explicit guidelines for continuing rounds in coordinator prompt - Prevent LLM from starting new topics during clarification - Ensure topic continuity across clarification rounds Fixes issue where LLM would restart clarification instead of building upon previous exchanges. * fix: Add conversation history to clarification context * fix: resolve clarification feature message to planer, prompt, test issues - Optimize coordinator.md prompt template for better clarification flow - Simplify final message sent to planner after clarification - Fix API key assertion issues in test_search.py * fix: Add configurable max_clarification_rounds and comprehensive tests - Add max_clarification_rounds parameter for external configuration - Add comprehensive test cases for clarification feature in test_app.py - Fixes issues found during interactive mode testing where: - Recursive call failed due to missing initial_state parameter - Clarification exited prematurely at max rounds - Incorrect logging of max rounds reached * Move clarification tests to test_nodes.py and add max_clarification_rounds to zh.json * fix: add max_clarification_rounds parameter passing from frontend to backend - Add max_clarification_rounds parameter in store.ts sendMessage function - Add max_clarification_rounds type definition in chat.ts - Ensure frontend settings page clarification rounds are correctly passed to backend * fix: refine clarification workflow state handling and coverage - Add clarification history reconstruction - Fix clarified topic accumulation - Add clarified_research_topic state field - Preserve clarification state in recursive calls - Add comprehensive test coverage * refactor: optimize coordinator logic and type annotations - Simplify handoff topic logic in coordinator_node - Update type annotations from Tuple to tuple - Improve code readability and maintainability --------- Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
72 lines
2.4 KiB
Python
72 lines
2.4 KiB
Python
# Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
# SPDX-License-Identifier: MIT
|
|
|
|
import logging
|
|
import os
|
|
from dataclasses import dataclass, field, fields
|
|
from typing import Any, Optional
|
|
|
|
from langchain_core.runnables import RunnableConfig
|
|
|
|
from src.config.loader import get_bool_env, get_int_env, get_str_env
|
|
from src.config.report_style import ReportStyle
|
|
from src.rag.retriever import Resource
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def get_recursion_limit(default: int = 25) -> int:
|
|
"""Get the recursion limit from environment variable or use default.
|
|
|
|
Args:
|
|
default: Default recursion limit if environment variable is not set or invalid
|
|
|
|
Returns:
|
|
int: The recursion limit to use
|
|
"""
|
|
env_value_str = get_str_env("AGENT_RECURSION_LIMIT", str(default))
|
|
parsed_limit = get_int_env("AGENT_RECURSION_LIMIT", default)
|
|
|
|
if parsed_limit > 0:
|
|
logger.info(f"Recursion limit set to: {parsed_limit}")
|
|
return parsed_limit
|
|
else:
|
|
logger.warning(
|
|
f"AGENT_RECURSION_LIMIT value '{env_value_str}' (parsed as {parsed_limit}) is not positive. "
|
|
f"Using default value {default}."
|
|
)
|
|
return default
|
|
|
|
|
|
@dataclass(kw_only=True)
|
|
class Configuration:
|
|
"""The configurable fields."""
|
|
|
|
resources: list[Resource] = field(
|
|
default_factory=list
|
|
) # Resources to be used for the research
|
|
max_plan_iterations: int = 1 # Maximum number of plan iterations
|
|
max_step_num: int = 3 # Maximum number of steps in a plan
|
|
max_search_results: int = 3 # Maximum number of search results
|
|
mcp_settings: dict = None # MCP settings, including dynamic loaded tools
|
|
report_style: str = ReportStyle.ACADEMIC.value # Report style
|
|
enable_deep_thinking: bool = False # Whether to enable deep thinking
|
|
enforce_web_search: bool = (
|
|
False # Enforce at least one web search step in every plan
|
|
)
|
|
|
|
@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})
|