Coverage for src/local_deep_research/advanced_search_system/questions/flexible_browsecomp_question.py: 98%

27 statements  

« prev     ^ index     » next       coverage.py v7.16.0, created at 2026-09-06 15:42 +0000

1""" 

2Flexible BrowseComp question generator with less prescriptive instructions. 

3 

4Inherits from BrowseComp but gives the LLM more freedom in search strategy. 

5""" 

6 

7from typing import Dict, List 

8 

9from ...utilities.json_utils import get_llm_response_text 

10from .browsecomp_question import BrowseCompQuestionGenerator 

11 

12 

13class FlexibleBrowseCompQuestionGenerator(BrowseCompQuestionGenerator): 

14 """ 

15 BrowseComp variant with simplified, less prescriptive prompts. 

16 

17 Gives the LLM more freedom to explore different search strategies 

18 instead of strict entity-combination rules. 

19 """ 

20 

21 def _generate_progressive_searches( 

22 self, 

23 query: str, 

24 current_knowledge: str, 

25 entities: Dict[str, List[str]], 

26 questions_by_iteration: dict, 

27 results_by_iteration: dict, 

28 num_questions: int, 

29 iteration: int, 

30 ) -> List[str]: 

31 """Generate searches with more freedom and less rigid instructions.""" 

32 

33 # Check if recent searches are failing 

34 recent_iterations = list(range(max(1, iteration - 5), iteration)) 

35 zero_count = sum( 

36 1 for i in recent_iterations if results_by_iteration.get(i, 1) == 0 

37 ) 

38 searches_failing = zero_count >= 3 

39 

40 # Simpler strategy hint 

41 if searches_failing: 

42 hint = "Recent searches returned 0 results. Try broader, simpler queries." 

43 else: 

44 hint = "Continue exploring to answer the query." 

45 

46 # Much simpler prompt - less prescriptive 

47 prompt = f"""Generate {num_questions} new search queries for: {query} 

48 

49{hint} 

50 

51Available terms: {", ".join(entities["names"] + entities["temporal"] + entities["descriptors"])} 

52 

53Previous searches with results: 

54{self._format_previous_searches(questions_by_iteration, results_by_iteration)} 

55 

56Current findings: 

57{current_knowledge[: self.knowledge_truncate_length] if self.knowledge_truncate_length else current_knowledge} 

58 

59Create {num_questions} diverse search queries. Avoid exact duplicates. One per line. 

60""" 

61 

62 response = self.model.invoke(prompt) 

63 content = get_llm_response_text(response) 

64 

65 # Extract searches 

66 searches = [] 

67 for line in content.strip().split("\n"): 

68 line = line.strip() 

69 if line and not line.endswith(":") and len(line) > 5: 

70 for prefix in [ 

71 "Q:", 

72 "Search:", 

73 "-", 

74 "*", 

75 "•", 

76 "1.", 

77 "2.", 

78 "3.", 

79 "4.", 

80 "5.", 

81 ]: 

82 if line.startswith(prefix): 

83 line = line[len(prefix) :].strip() 

84 if line: 84 ↛ 67line 84 didn't jump to line 67 because the condition on line 84 was always true

85 searches.append(line) 

86 

87 # If not enough, fall back to parent's logic 

88 if len(searches) < num_questions: 

89 parent_searches = super()._generate_progressive_searches( 

90 query, 

91 current_knowledge, 

92 entities, 

93 questions_by_iteration, 

94 results_by_iteration, 

95 num_questions - len(searches), 

96 iteration, 

97 ) 

98 searches.extend(parent_searches) 

99 

100 return searches[:num_questions]