Coverage for src / local_deep_research / citation_handlers / standard_citation_handler.py: 100%

26 statements  

« prev     ^ index     » next       coverage.py v7.12.0, created at 2026-01-11 00:51 +0000

1""" 

2Standard citation handler - the original implementation. 

3""" 

4 

5from datetime import datetime, timezone 

6from typing import Any, Dict, List, Union 

7 

8from .base_citation_handler import BaseCitationHandler 

9 

10 

11class StandardCitationHandler(BaseCitationHandler): 

12 """Standard citation handler with detailed analysis.""" 

13 

14 def analyze_initial( 

15 self, query: str, search_results: Union[str, List[Dict]] 

16 ) -> Dict[str, Any]: 

17 documents = self._create_documents(search_results) 

18 formatted_sources = self._format_sources(documents) 

19 current_timestamp = datetime.now(timezone.utc).strftime( 

20 "%Y-%m-%d %H:%M" 

21 ) 

22 

23 output_prefix = self._get_output_instruction_prefix() 

24 

25 prompt = f"""{output_prefix}Analyze the following information concerning the question and include citations using numbers in square brackets [1], [2], etc. When citing, use the source number provided at the start of each source. 

26 

27Question: {query} 

28 

29Sources: 

30{formatted_sources} 

31 

32Current time is {current_timestamp} UTC for verifying temporal references in sources. 

33 

34Provide a detailed analysis with citations. Do not create the bibliography, it will be provided automatically. Never make up sources. Never write or create urls. Only write text relevant to the question. Example format: "According to the research [1], ..." 

35""" 

36 

37 response = self.llm.invoke(prompt) 

38 if not isinstance(response, str): 

39 response = response.content 

40 return {"content": response, "documents": documents} 

41 

42 def analyze_followup( 

43 self, 

44 question: str, 

45 search_results: Union[str, List[Dict]], 

46 previous_knowledge: str, 

47 nr_of_links: int, 

48 ) -> Dict[str, Any]: 

49 """Process follow-up analysis with citations.""" 

50 documents = self._create_documents( 

51 search_results, nr_of_links=nr_of_links 

52 ) 

53 formatted_sources = self._format_sources(documents) 

54 # Add fact-checking step 

55 fact_check_prompt = f"""Analyze these sources for factual consistency: 

561. Cross-reference major claims between sources 

572. Identify and flag any contradictions 

583. Verify basic facts (dates, company names, ownership) 

594. Note when sources disagree 

60 

61Previous Knowledge: 

62{previous_knowledge} 

63 

64New Sources: 

65{formatted_sources} 

66 

67 Return any inconsistencies or conflicts found.""" 

68 if self.get_setting("general.enable_fact_checking", True): 

69 fact_check_response = self.llm.invoke(fact_check_prompt).content 

70 

71 else: 

72 fact_check_response = "" 

73 

74 current_timestamp = datetime.now(timezone.utc).strftime( 

75 "%Y-%m-%d %H:%M" 

76 ) 

77 

78 output_prefix = self._get_output_instruction_prefix() 

79 

80 prompt = f"""{output_prefix}Using the previous knowledge and new sources, answer the question. Include citations using numbers in square brackets [1], [2], etc. When citing, use the source number provided at the start of each source. Reflect information from sources critically. 

81 

82Previous Knowledge: 

83{previous_knowledge} 

84 

85Question: {question} 

86 

87New Sources: 

88{formatted_sources} 

89 

90Current time is {current_timestamp} UTC for verifying temporal references in sources. 

91 

92Reflect information from sources critically based on: {fact_check_response}. Never invent sources. 

93Provide a detailed answer with citations. Example format: "According to [1], ..." """ 

94 

95 response = self.llm.invoke(prompt) 

96 

97 return {"content": response.content, "documents": documents}