Skip to content

Commit f4dc37f

Browse files
authored
Markdown formatting for chat history (#444)
1 parent 1cb61de commit f4dc37f

File tree

3 files changed

+57
-8
lines changed

3 files changed

+57
-8
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,8 @@ sgpt --role json_generator "random: user, password, email, address"
365365
}
366366
```
367367

368+
If the description of the role contains the words "APPLY MARKDOWN" (case sensitive), then chats will be displayed using markdown formatting.
369+
368370
### Request cache
369371
Control cache using `--cache` (default) and `--no-cache` options. This caching applies for all `sgpt` requests to OpenAI API:
370372
```shell

sgpt/handlers/chat_handler.py

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
import typer
66
from click import BadArgumentUsage
7+
from rich.console import Console
8+
from rich.markdown import Markdown
79

810
from ..config import cfg
911
from ..role import DefaultRoles, SystemRole
@@ -107,15 +109,15 @@ def __init__(self, chat_id: str, role: SystemRole) -> None:
107109
def initiated(self) -> bool:
108110
return self.chat_session.exists(self.chat_id)
109111

110-
@property
111-
def initial_message(self) -> str:
112-
chat_history = self.chat_session.get_messages(self.chat_id)
113-
return chat_history[0] if chat_history else ""
114-
115112
@property
116113
def is_same_role(self) -> bool:
117114
# TODO: Should be optimized for REPL mode.
118-
return self.role.same_role(self.initial_message)
115+
return self.role.same_role(self.initial_message(self.chat_id))
116+
117+
@classmethod
118+
def initial_message(cls, chat_id: str) -> str:
119+
chat_history = cls.chat_session.get_messages(chat_id)
120+
return chat_history[0] if chat_history else ""
119121

120122
@classmethod
121123
@option_callback
@@ -126,7 +128,15 @@ def list_ids(cls, value: str) -> None:
126128

127129
@classmethod
128130
def show_messages(cls, chat_id: str) -> None:
129-
# Prints all messages from a specified chat ID to the console.
131+
if "APPLY MARKDOWN" in cls.initial_message(chat_id):
132+
for message in cls.chat_session.get_messages(chat_id):
133+
if message.startswith("assistant:"):
134+
Console().print(Markdown(message))
135+
else:
136+
typer.secho(message, fg=cfg.get("DEFAULT_COLOR"))
137+
typer.echo()
138+
return
139+
130140
for index, message in enumerate(cls.chat_session.get_messages(chat_id)):
131141
color = "magenta" if index % 2 == 0 else "green"
132142
typer.secho(message, fg=color)
@@ -138,7 +148,7 @@ def show_messages_callback(cls, chat_id: str) -> None:
138148

139149
def validate(self) -> None:
140150
if self.initiated:
141-
chat_role_name = self.role.get_role_name(self.initial_message)
151+
chat_role_name = self.role.get_role_name(self.initial_message(self.chat_id))
142152
if not chat_role_name:
143153
raise BadArgumentUsage(
144154
f'Could not determine chat role of "{self.chat_id}"'

tests/test_default.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,43 @@ def test_default_stdin(completion):
3838
assert "Prague" in result.stdout
3939

4040

41+
@patch("rich.console.Console.print")
42+
@patch("litellm.completion")
43+
def test_show_chat_use_markdown(completion, console_print):
44+
completion.return_value = mock_comp("ok")
45+
chat_name = "_test"
46+
chat_path = Path(cfg.get("CHAT_CACHE_PATH")) / chat_name
47+
chat_path.unlink(missing_ok=True)
48+
49+
args = {"prompt": "my number is 2", "--chat": chat_name}
50+
result = runner.invoke(app, cmd_args(**args))
51+
assert result.exit_code == 0
52+
assert chat_path.exists()
53+
54+
result = runner.invoke(app, ["--show-chat", chat_name])
55+
assert result.exit_code == 0
56+
console_print.assert_called()
57+
58+
59+
@patch("rich.console.Console.print")
60+
@patch("litellm.completion")
61+
def test_show_chat_no_use_markdown(completion, console_print):
62+
completion.return_value = mock_comp("ok")
63+
chat_name = "_test"
64+
chat_path = Path(cfg.get("CHAT_CACHE_PATH")) / chat_name
65+
chat_path.unlink(missing_ok=True)
66+
67+
# Flag '--code' doesn't use markdown
68+
args = {"prompt": "my number is 2", "--chat": chat_name, "--code": True}
69+
result = runner.invoke(app, cmd_args(**args))
70+
assert result.exit_code == 0
71+
assert chat_path.exists()
72+
73+
result = runner.invoke(app, ["--show-chat", chat_name])
74+
assert result.exit_code == 0
75+
console_print.assert_not_called()
76+
77+
4178
@patch("litellm.completion")
4279
def test_default_chat(completion):
4380
completion.side_effect = [mock_comp("ok"), mock_comp("4")]

0 commit comments

Comments
 (0)