pylogue 0.2.0__tar.gz → 0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pylogue-0.2.0 → pylogue-0.3}/PKG-INFO +1 -1
- {pylogue-0.2.0 → pylogue-0.3}/README.md +6 -4
- {pylogue-0.2.0 → pylogue-0.3}/pyproject.toml +1 -1
- {pylogue-0.2.0 → pylogue-0.3}/src/pylogue/__init__.py +2 -0
- {pylogue-0.2.0 → pylogue-0.3}/src/pylogue/_modidx.py +1 -0
- {pylogue-0.2.0 → pylogue-0.3}/src/pylogue/cards.py +27 -10
- {pylogue-0.2.0 → pylogue-0.3}/src/pylogue/chatapp.py +15 -9
- {pylogue-0.2.0 → pylogue-0.3}/src/pylogue/renderer.py +12 -1
- {pylogue-0.2.0 → pylogue-0.3}/src/pylogue.egg-info/PKG-INFO +1 -1
- {pylogue-0.2.0 → pylogue-0.3}/AUTHORS.md +0 -0
- {pylogue-0.2.0 → pylogue-0.3}/CONTRIBUTING.md +0 -0
- {pylogue-0.2.0 → pylogue-0.3}/LICENSE +0 -0
- {pylogue-0.2.0 → pylogue-0.3}/MANIFEST.in +0 -0
- {pylogue-0.2.0 → pylogue-0.3}/setup.cfg +0 -0
- {pylogue-0.2.0 → pylogue-0.3}/src/pylogue/__pre_init__.py +0 -0
- {pylogue-0.2.0 → pylogue-0.3}/src/pylogue/chat.py +0 -0
- {pylogue-0.2.0 → pylogue-0.3}/src/pylogue/health.py +0 -0
- {pylogue-0.2.0 → pylogue-0.3}/src/pylogue/service.py +0 -0
- {pylogue-0.2.0 → pylogue-0.3}/src/pylogue/session.py +0 -0
- {pylogue-0.2.0 → pylogue-0.3}/src/pylogue.egg-info/SOURCES.txt +0 -0
- {pylogue-0.2.0 → pylogue-0.3}/src/pylogue.egg-info/dependency_links.txt +0 -0
- {pylogue-0.2.0 → pylogue-0.3}/src/pylogue.egg-info/entry_points.txt +0 -0
- {pylogue-0.2.0 → pylogue-0.3}/src/pylogue.egg-info/requires.txt +0 -0
- {pylogue-0.2.0 → pylogue-0.3}/src/pylogue.egg-info/top_level.txt +0 -0
- {pylogue-0.2.0 → pylogue-0.3}/tests/__init__.py +0 -0
- {pylogue-0.2.0 → pylogue-0.3}/tests/test_pylogue.py +0 -0
|
@@ -20,7 +20,7 @@ app.run(port=5001)
|
|
|
20
20
|
### Custom Styling
|
|
21
21
|
|
|
22
22
|
``` python
|
|
23
|
-
from pylogue.
|
|
23
|
+
from pylogue.card import ChatCard
|
|
24
24
|
from pylogue.chatapp import create_default_chat_app, ChatAppConfig
|
|
25
25
|
|
|
26
26
|
card = ChatCard(
|
|
@@ -51,7 +51,7 @@ from pylogue.chatapp import ChatApp, ChatAppConfig
|
|
|
51
51
|
from pylogue.session import InMemorySessionManager
|
|
52
52
|
from pylogue.service import ChatService
|
|
53
53
|
from pylogue.renderer import ChatRenderer
|
|
54
|
-
from pylogue.
|
|
54
|
+
from pylogue.card import ChatCard
|
|
55
55
|
|
|
56
56
|
# 1. Configure components
|
|
57
57
|
session_manager = InMemorySessionManager()
|
|
@@ -162,7 +162,7 @@ html = renderer.render_messages(messages)
|
|
|
162
162
|
|
|
163
163
|
## 📚 Examples
|
|
164
164
|
|
|
165
|
-
See `
|
|
165
|
+
See `6-Examples.ipynb` for complete working examples:
|
|
166
166
|
|
|
167
167
|
1. **Echo Bot** - Simplest possible implementation
|
|
168
168
|
2. **Custom Styled Chat** - UI/UX customization
|
|
@@ -250,10 +250,12 @@ app = create_default_chat_app(responder=your_responder)
|
|
|
250
250
|
- `3-Renderer.ipynb` - Explore presentation layer
|
|
251
251
|
- `4-ChatApp.ipynb` - See full integration
|
|
252
252
|
- `5-Examples.ipynb` - Working examples
|
|
253
|
+
- `6-JupyterExample.ipynb` - Jupyter integration
|
|
253
254
|
|
|
254
255
|
2. Try the examples in `5-Examples.ipynb`
|
|
255
256
|
|
|
256
|
-
3. Build your own custom responder
|
|
257
|
+
3. Build your own custom responder and test it out in
|
|
258
|
+
`6-JupyterExample.ipynb`
|
|
257
259
|
|
|
258
260
|
4. Deploy to production with your preferred hosting
|
|
259
261
|
|
|
@@ -11,6 +11,7 @@ d = { 'settings': { 'branch': 'main',
|
|
|
11
11
|
'pylogue.cards.ChatCard._get_role_style': ('0-card.html#chatcard._get_role_style', 'pylogue/cards.py'),
|
|
12
12
|
'pylogue.cards.ChatCard._get_style': ('0-card.html#chatcard._get_style', 'pylogue/cards.py'),
|
|
13
13
|
'pylogue.cards.ChatCard._get_text_color': ('0-card.html#chatcard._get_text_color', 'pylogue/cards.py'),
|
|
14
|
+
'pylogue.cards.ChatCard.get_mobile_styles': ('0-card.html#chatcard.get_mobile_styles', 'pylogue/cards.py'),
|
|
14
15
|
'pylogue.cards.ChatCard.render': ('0-card.html#chatcard.render', 'pylogue/cards.py'),
|
|
15
16
|
'pylogue.cards.mk_inp': ('0-card.html#mk_inp', 'pylogue/cards.py'),
|
|
16
17
|
'pylogue.cards.render_chat_list': ('0-card.html#render_chat_list', 'pylogue/cards.py')},
|
|
@@ -14,18 +14,19 @@ class ChatCard:
|
|
|
14
14
|
assistant_color: str = "#004539",
|
|
15
15
|
user_emoji: str = "🗣️",
|
|
16
16
|
assistant_emoji: str = "🕵️♂️",
|
|
17
|
-
|
|
17
|
+
max_width: str = "80%",
|
|
18
|
+
card_max_width: str = "60%",
|
|
18
19
|
font_size: str = "1.5em",
|
|
20
|
+
mobile_font_size: str = "16px",
|
|
19
21
|
padding: str = "1.25em",
|
|
20
|
-
border_radius: str = "1em",
|
|
21
22
|
user_align: str = "right",
|
|
22
23
|
assistant_align: str = "left",
|
|
23
|
-
user_self_align: str = "
|
|
24
|
-
assistant_self_align: str = "
|
|
24
|
+
user_self_align: str = "flex-end",
|
|
25
|
+
assistant_self_align: str = "flex-start",
|
|
25
26
|
role_font_weight: str = "bold",
|
|
26
27
|
role_font_size: str = "1.1em",
|
|
27
28
|
role_margin_bottom: str = "8px",
|
|
28
|
-
content_white_space: str = "
|
|
29
|
+
content_white_space: str = "normal",
|
|
29
30
|
spinner_class: str = "spinner",
|
|
30
31
|
):
|
|
31
32
|
self.colors = {
|
|
@@ -40,11 +41,14 @@ class ChatCard:
|
|
|
40
41
|
"Assistant": {"text": assistant_align, "self": assistant_self_align},
|
|
41
42
|
}
|
|
42
43
|
|
|
44
|
+
self.border_radii = {"User": "1em 1em 0em 1em", "Assistant": "1em 1em 1em 0em"}
|
|
45
|
+
|
|
43
46
|
# Style configuration
|
|
44
|
-
self.
|
|
47
|
+
self.card_max_width = card_max_width
|
|
48
|
+
self.max_width = max_width
|
|
45
49
|
self.font_size = font_size
|
|
50
|
+
self.mobile_font_size = mobile_font_size
|
|
46
51
|
self.padding = padding
|
|
47
|
-
self.border_radius = border_radius
|
|
48
52
|
self.role_font_weight = role_font_weight
|
|
49
53
|
self.role_font_size = role_font_size
|
|
50
54
|
self.role_margin_bottom = role_margin_bottom
|
|
@@ -54,8 +58,8 @@ class ChatCard:
|
|
|
54
58
|
# Build style template
|
|
55
59
|
self.style_template = f"""
|
|
56
60
|
background: {{bg}}; color: {{text_color}}; padding: 10px; font-size: {self.font_size};
|
|
57
|
-
width: {self.
|
|
58
|
-
text-align: {{text_align}}; border-radius: {
|
|
61
|
+
max-width: min({self.card_max_width}, {self.max_width}); align-self: {{self_align}};
|
|
62
|
+
text-align: {{text_align}}; border-radius: {{border_radius}};
|
|
59
63
|
padding: {self.padding}"""
|
|
60
64
|
|
|
61
65
|
def _get_text_color(self, bg_color: str) -> str:
|
|
@@ -89,12 +93,23 @@ class ChatCard:
|
|
|
89
93
|
text_color=self._get_text_color(bg_color),
|
|
90
94
|
self_align=self.alignments[role]["self"],
|
|
91
95
|
text_align=self.alignments[role]["text"],
|
|
96
|
+
border_radius=self.border_radii[role],
|
|
92
97
|
)
|
|
93
98
|
|
|
94
99
|
def _get_role_style(self) -> str:
|
|
95
100
|
"""Generate CSS style string for role labels."""
|
|
96
101
|
return f"font-weight: {self.role_font_weight}; font-size: {self.role_font_size}; display: block; margin-bottom: {self.role_margin_bottom};"
|
|
97
102
|
|
|
103
|
+
def get_mobile_styles(self) -> str:
|
|
104
|
+
"""Generate CSS media query for mobile devices."""
|
|
105
|
+
return f"""
|
|
106
|
+
@media (max-width: 768px) {{
|
|
107
|
+
.chat-card {{
|
|
108
|
+
font-size: {self.mobile_font_size} !important;
|
|
109
|
+
}}
|
|
110
|
+
}}
|
|
111
|
+
"""
|
|
112
|
+
|
|
98
113
|
def render(self, data: dict):
|
|
99
114
|
"""
|
|
100
115
|
Render a chat card with the given data.
|
|
@@ -117,7 +132,7 @@ class ChatCard:
|
|
|
117
132
|
|
|
118
133
|
if pending:
|
|
119
134
|
spinner = Span(cls=self.spinner_class)
|
|
120
|
-
return Div(f"{emoji} {role}: ", spinner, style=style)
|
|
135
|
+
return Div(f"{emoji} {role}: ", spinner, style=style, cls="chat-card")
|
|
121
136
|
|
|
122
137
|
# Add 'marked' class to enable markdown rendering
|
|
123
138
|
return Div(
|
|
@@ -129,6 +144,7 @@ class ChatCard:
|
|
|
129
144
|
content, cls="marked", style=f"white-space: {self.content_white_space};"
|
|
130
145
|
),
|
|
131
146
|
style=style,
|
|
147
|
+
cls="chat-card",
|
|
132
148
|
)
|
|
133
149
|
|
|
134
150
|
def __call__(self, data: dict):
|
|
@@ -141,6 +157,7 @@ CHAT_DIV_ID = "chat-cards"
|
|
|
141
157
|
|
|
142
158
|
def render_chat_list(messages: List[Dict[str, str]], ChatCard: ChatCard):
|
|
143
159
|
return Div(
|
|
160
|
+
Style(ChatCard.get_mobile_styles()),
|
|
144
161
|
*[ChatCard(m) for m in messages],
|
|
145
162
|
id=CHAT_DIV_ID,
|
|
146
163
|
cls="chat-cards",
|
|
@@ -34,6 +34,7 @@ class ChatAppConfig:
|
|
|
34
34
|
|
|
35
35
|
# WebSocket settings
|
|
36
36
|
ws_endpoint: str = "/ws"
|
|
37
|
+
chat_endpoint: str = "/chat"
|
|
37
38
|
|
|
38
39
|
# FastHTML extensions and headers
|
|
39
40
|
markdown_enabled: bool = True
|
|
@@ -120,6 +121,9 @@ class ChatApp:
|
|
|
120
121
|
# Add spinner styles
|
|
121
122
|
headers.append(Style(self.config.get_spinner_style()))
|
|
122
123
|
|
|
124
|
+
# Add mobile responsive styles from ChatCard
|
|
125
|
+
headers.append(Style(self.renderer.card.get_mobile_styles()))
|
|
126
|
+
|
|
123
127
|
return FastHTML(exts="ws", hdrs=tuple(headers))
|
|
124
128
|
|
|
125
129
|
def _get_initial_messages(self) -> List[Message]:
|
|
@@ -131,23 +135,25 @@ class ChatApp:
|
|
|
131
135
|
def _register_routes(self):
|
|
132
136
|
"""Register HTTP and WebSocket routes."""
|
|
133
137
|
|
|
134
|
-
@self.app.route(
|
|
135
|
-
def
|
|
138
|
+
@self.app.route(self.config.chat_endpoint)
|
|
139
|
+
def chat():
|
|
136
140
|
"""Main chat interface."""
|
|
137
141
|
initial_messages = self._get_initial_messages()
|
|
138
142
|
|
|
139
143
|
container_style = self.config.container_style or (
|
|
140
144
|
f"font-family: monospace, sans-serif; margin: 0; padding: 0; "
|
|
141
|
-
f"background: {self.config.bg_color}; min-height: 100vh;"
|
|
142
145
|
)
|
|
143
146
|
|
|
144
147
|
return (
|
|
145
148
|
Title(self.config.page_title),
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
149
|
+
Body(
|
|
150
|
+
Div(
|
|
151
|
+
H1(self.config.app_title, style=self.config.header_style),
|
|
152
|
+
self.renderer.render_messages(initial_messages),
|
|
153
|
+
self.renderer.render_form(),
|
|
154
|
+
style=container_style,
|
|
155
|
+
),
|
|
156
|
+
style="background-color: #000",
|
|
151
157
|
),
|
|
152
158
|
)
|
|
153
159
|
|
|
@@ -210,7 +216,7 @@ class ChatApp:
|
|
|
210
216
|
assistant_msg.id, content=full_response, pending=False
|
|
211
217
|
)
|
|
212
218
|
# Send updated message list to UI
|
|
213
|
-
print(f"📤 Sending chunk #{chunk_count}: {repr(chunk)}") # Debug
|
|
219
|
+
# print(f"📤 Sending chunk #{chunk_count}: {repr(chunk)}") # Debug
|
|
214
220
|
await send(self.renderer.render_messages(session.get_messages()))
|
|
215
221
|
|
|
216
222
|
except Exception as e:
|
|
@@ -41,7 +41,7 @@ class ChatRenderer:
|
|
|
41
41
|
"font-size: 1em; border-radius: 0.5em"
|
|
42
42
|
)
|
|
43
43
|
self.chat_container_style = chat_container_style or (
|
|
44
|
-
"display: flex; flex-direction: column; gap:
|
|
44
|
+
"display: flex; flex-direction: column; gap: 1em; margin: 3em;"
|
|
45
45
|
)
|
|
46
46
|
|
|
47
47
|
def render_message(self, message: Message) -> Any:
|
|
@@ -58,7 +58,18 @@ class ChatRenderer:
|
|
|
58
58
|
Returns:
|
|
59
59
|
FastHTML Div containing all rendered messages
|
|
60
60
|
"""
|
|
61
|
+
# Add mobile-responsive margin CSS
|
|
62
|
+
mobile_margin_css = """
|
|
63
|
+
@media (max-width: 768px) {
|
|
64
|
+
.chat-cards {
|
|
65
|
+
margin: 1em !important;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
"""
|
|
69
|
+
|
|
61
70
|
return Div(
|
|
71
|
+
Style(self.card.get_mobile_styles()),
|
|
72
|
+
Style(mobile_margin_css),
|
|
62
73
|
*[self.render_message(msg) for msg in messages],
|
|
63
74
|
id=self.CHAT_DIV_ID,
|
|
64
75
|
cls="chat-cards",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|