File size: 3,953 Bytes
1b9f020
9d0c72d
040f332
 
1b9f020
6355201
040f332
1b9f020
 
 
 
 
 
 
 
 
 
 
 
 
 
040f332
 
1b9f020
 
 
 
 
040f332
1b9f020
9d0c72d
040f332
 
1b9f020
 
 
 
 
 
 
 
 
6355201
 
 
 
 
1b9f020
6355201
 
 
1b9f020
6355201
 
 
 
 
 
 
 
 
1b9f020
 
 
 
 
 
 
 
 
 
 
040f332
 
1b9f020
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
040f332
1b9f020
040f332
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
from langchain import PromptTemplate, LLMChain
from .re_act import ReActStrategy, get_re_act_config
from .tree_of_thought import TreeOfThoughtStrategy, get_tot_config
from .chain_of_thought import ChainOfThoughtStrategy, get_cot_confg
from .reasoning_strategy import ReasoningConfig
from typing import Tuple, Callable, Optional
import pprint
import re
import os

class ReasoningRouter:
    def __init__(self, api_key: str, config: ReasoningConfig, question:str, display: Callable):
        """
        Initializes a ReasoningRouter instance.

        Args:
            question (str): The user's question.

        Returns:
            None
        """
        print("Creating Reasoning Router with config: ",)
        pprint.pprint(vars(config))
        self.api_key = api_key
        self.llm  = config.llm_class(temperature=config.temperature, max_tokens=config.max_tokens)
        self.question: str = question
        self.display: Callable = display


        self.strategies = {
            1: ReActStrategy(get_re_act_config(temperature=config.temperature), display=self.display),
            2: TreeOfThoughtStrategy(get_tot_config(temperature=config.temperature),display=self.display),
            3: ChainOfThoughtStrategy(get_cot_confg(temperature=config.temperature),display=self.display)
        }
        self.usage_block = f"""

        1. {self.strategies[1].usage} [1].
        2. {self.strategies[2].usage} [2].
        3. {self.strategies[3].usage} [3].

        """
        self.template = """
        Consider the following problem or puzzle: {question}. Based on the characteristics of the problem,
        identify the most suitable approach among the three techniques described below. consider each carefully 
        in the context of the question, write out the likelihood of success of each, and then select the most 
        appropriate approach:""" + self.usage_block + """
            Based on the characteristics of the given problem or puzzle, select the technique that aligns most closely with the nature of the problem. It is important to first provide the number of the technique that best solves the problem, followed by a period. Then you may provide your reason why you have chosen this technique. 

        The number of the selected technique is...
        """
        
    @staticmethod
    def find_first_integer(text: str) -> Optional[int]:
        """Finds the first integer in a string.

        Args:
            text (str): The string to search for an integer.

        Returns:
            int or None: The first integer found in the string, or None if no integer is found.
        """
        match = re.search(r'\d+', text)
        if match:
            return int(match.group())
        else:
            return None

    def determine_and_execute(self) -> Tuple[str, str]:
        """
        Determines the appropriate reasoning strategy based on the user's question and executes it.

        Returns:
            response : Reason the strategy was selected
            strat_response : Response from the strategy 
        """
        
        prompt = PromptTemplate(template=self.template, input_variables=["question"])
        llm_chain = LLMChain(prompt=prompt, llm=self.llm)

        response = llm_chain.run(self.question)
        print(response)
        self.display(response)
        n = self.find_first_integer(response)

        if n in self.strategies:
            strat_resp = self.strategies[n].run(self.question)
        else:
            strat_resp = (f"Strategy number {n} is not recognized.")
            print(strat_resp)
            
        return response, strat_resp

def get_reasoning_router_config(temperature: float = 0.6) -> ReasoningConfig:
    usage="This router should be used when determing the most effective strategy for a query requiring more complex, but general reasoning to derive"
    return ReasoningConfig(temperature=temperature, max_tokens=3000, usage=usage)