File size: 2,589 Bytes
8bd8cd0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
from typing import Tuple

import logging

from langchain_core.messages import AIMessage, HumanMessage

def add_details(response: str, reasoning: str, svg_argmap: str) -> str:
    """Add reasoning details to the response message shown in chat."""
    response_with_details = (
        f"<p>{response}</p>"
        '<details id="reasoning">'
        "<summary><i>Internal reasoning trace</i></summary>"
        f"<code>{reasoning}</code></details>"
        '<details id="svg_argmap">'
        "<summary><i>Argument map</i></summary>"
        f"\n<div>\n{svg_argmap}\n</div>\n</details>"
    )
    return response_with_details


def get_details(response_with_details: str) -> Tuple[str, dict[str, str]]:
    """Extract response and details from response_with_details shown in chat."""
    if "<details id=" not in response_with_details:
        return response_with_details, {}
    details_dict = {}
    response, *details_raw = response_with_details.split('<details id="')
    for details in details_raw:
        details_id, details_content = details.split('"', maxsplit=1)
        details_content = details_content.strip()
        if details_content.endswith("</code></details>"):
            details_content = details_content.split("<code>")[1].strip()
            details_content = details_content[:-len("</code></details>")].strip()
        elif details_content.endswith("</div></details>"):
            details_content = details_content.split("<div>")[1].strip()
            details_content = details_content[:-len("</div></details>")].strip()
        else:
            logging.warning(f"Unrecognized details content: {details_content}")
            details_content = "UNRECOGNIZED DETAILS CONTENT"
        details_dict[details_id] = details_content
    return response, details_dict


def history_to_langchain_format(history: list[tuple[str, str]]) -> list:
    history_langchain_format = []  # History in LangChain format, as shown to the LLM
    for human, ai in history:
        history_langchain_format.append(HumanMessage(content=human))
        if ai is None:
            continue
        response, details = get_details(ai)
        logging.debug(f"Details: {details}")
        content = response
        if "reasoning" in details:
            content += (
                "\n\n"
                "#+BEGIN_INTERNAL_TRACE // Internal reasoning trace (hidden from user)\n"
                f"{details.get('reasoning', '')}\n"
                "#+END_INTERNAL_TRACE"
            )
        history_langchain_format.append(AIMessage(content=content))
    return history_langchain_format