# pocketgroq/chain_of_thought/cot_manager.py

from typing import List
from .llm_interface import LLMInterface
from .utils import sanitize_input

class ChainOfThoughtManager:
    """
    Manages the Chain-of-Thought reasoning process.
    """
    def __init__(self, llm: LLMInterface, cot_prompt_template: str = None):
        """
        Initialize with an LLM instance and an optional CoT prompt template.
        """
        self.llm = llm
        self.cot_prompt_template = cot_prompt_template or (
            "Solve the following problem step by step:\n\n{problem}\n\nSolution:"
        )

    def generate_cot(self, problem: str) -> List[str]:
        """
        Generate intermediate reasoning steps (Chain-of-Thought) for the given problem.
        """
        sanitized_problem = sanitize_input(problem)
        prompt = self.cot_prompt_template.format(problem=sanitized_problem)
        response = self.llm.generate(prompt)
        cot_steps = self._parse_cot(response)
        return cot_steps

    def synthesize_response(self, cot_steps: List[str]) -> str:
        """
        Synthesize the final answer from the Chain-of-Thought steps.
        """
        synthesis_prompt = "Based on the following reasoning steps, provide a concise answer:\n\n"
        synthesis_prompt += "\n".join(cot_steps) + "\n\nAnswer:"
        final_response = self.llm.generate(synthesis_prompt)
        return final_response.strip()

    def solve_problem(self, problem: str) -> str:
        """
        Complete process to solve a problem using Chain-of-Thought.
        """
        cot = self.generate_cot(problem)
        answer = self.synthesize_response(cot)
        return answer

    def _parse_cot(self, response: str) -> List[str]:
        """
        Parse the LLM response to extract individual reasoning steps.
        This method can be customized based on how the LLM formats its output.
        """
        # Simple split by newline for demonstration; can be enhanced.
        steps = [line.strip() for line in response.split('\n') if line.strip()]
        return steps внедри эти предложения сделай рабочий код: Спасибо за предоставление содержимого файла `cot_manager.py`. Теперь я могу провести более детальный анализ и предложить улучшения для повышения эффективности работы цепочки мыслей и рассуждений. Вот несколько предложений:

1. Улучшение управления контекстом:
   - Добавьте механизм сохранения контекста между вызовами `generate_cot` и `synthesize_response`. Это позволит LLM лучше понимать контекст проблемы и предыдущие рассуждения.

```python
def __init__(self, llm: LLMInterface, cot_prompt_template: str = None):
    # ...
    self.context = []

def generate_cot(self, problem: str) -> List[str]:
    # ...
    self.context = cot_steps
    return cot_steps

def synthesize_response(self, cot_steps: List[str]) -> str:
    synthesis_prompt = f"Context:\n{self.context}\n\nBased on the following reasoning steps, provide a concise answer:\n\n"
    # ...
```

2. Реализация механизма проверки промежуточных результатов:
   - Добавьте метод для оценки качества каждого шага рассуждений.

```python
def evaluate_step(self, step: str) -> float:
    evaluation_prompt = f"Rate the relevance and correctness of this reasoning step from 0 to 1:\n{step}\n\nRating:"
    rating = float(self.llm.generate(evaluation_prompt).strip())
    return rating

def generate_cot(self, problem: str) -> List[str]:
    # ...
    cot_steps = self._parse_cot(response)
    filtered_steps = [step for step in cot_steps if self.evaluate_step(step) > 0.7]
    return filtered_steps
```

3. Добавление механизма итеративного уточнения:
   - Реализуйте метод для итеративного улучшения решения.

```python
def refine_solution(self, problem: str, initial_solution: str, iterations: int = 3) -> str:
    current_solution = initial_solution
    for _ in range(iterations):
        refine_prompt = f"Problem: {problem}\nCurrent solution: {current_solution}\nImprove this solution:"
        improved_solution = self.llm.generate(refine_prompt)
        if self.evaluate_step(improved_solution) > self.evaluate_step(current_solution):
            current_solution = improved_solution
    return current_solution

def solve_problem(self, problem: str) -> str:
    cot = self.generate_cot(problem)
    initial_answer = self.synthesize_response(cot)
    refined_answer = self.refine_solution(problem, initial_answer)
    return refined_answer
```

4. Улучшение обработки ошибок и восстановления:
   - Добавьте механизм повторных попыток и обработки исключений.

```python
from tenacity import retry, stop_after_attempt, wait_exponential

class LLMException(Exception):
    pass

@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10))
def _safe_llm_generate(self, prompt: str) -> str:
    try:
        return self.llm.generate(prompt)
    except Exception as e:
        raise LLMException(f"LLM generation failed: {str(e)}")

def generate_cot(self, problem: str) -> List[str]:
    # ...
    try:
        response = self._safe_llm_generate(prompt)
        # ...
    except LLMException:
        # Fallback to a simpler reasoning approach or return an error message
        return ["Unable to generate detailed reasoning steps."]
```

5. Добавление логирования и мониторинга:
   - Реализуйте систему логирования для отслеживания процесса рассуждений.

```python
import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class ChainOfThoughtManager:
    def __init__(self, llm: LLMInterface, cot_prompt_template: str = None):
        # ...
        self.logger = logger

    def generate_cot(self, problem: str) -> List[str]:
        self.logger.info(f"Generating CoT for problem: {problem[:50]}...")
        # ...
        self.logger.info(f"Generated {len(cot_steps)} CoT steps.")
        return cot_steps
```

6. Оптимизация использования токенов:
   - Добавьте механизм для контроля длины промежуточных шагов и общего количества токенов.

```python
def truncate_steps(self, steps: List[str], max_tokens: int = 1000) -> List[str]:
    total_tokens = 0
    truncated_steps = []
    for step in steps:
        step_tokens = len(step.split())
        if total_tokens + step_tokens > max_tokens:
            break
        truncated_steps.append(step)
        total_tokens += step_tokens
    return truncated_steps

def generate_cot(self, problem: str) -> List[str]:
    # ...
    cot_steps = self._parse_cot(response)
    return self.truncate_steps(cot_steps)
```

Эти улучшения помогут повысить эффективность, надежность и точность процесса рассуждений. Они также сделают систему более устойчивой к ошибкам и позволят лучше контролировать качество генерируемых решений.