from promplate.prompt import *#
promplate.prompt.builder #
CodeBuilder #
Build source code conveniently.Source code in
promplate/prompt/builder.py
code instance-attribute #
indent_level instance-attribute #
indent_str instance-attribute #
__init__ #
__str__ #
add_line #
add_section #
indent #
dedent #
get_render_function #
get_render_function() -> FunctionType
Execute the code, and return a dict of globals it defines.Source code in
promplate/prompt/builder.py
get_base_builder #
Source code in promplate/prompt/builder.py
promplate.prompt.chat #
U module-attribute #
U = MessageBuilder('user')
user module-attribute #
user = MessageBuilder('user')
A module-attribute #
A = MessageBuilder('assistant')
assistant module-attribute #
assistant = MessageBuilder('assistant')
S module-attribute #
S = MessageBuilder('system')
system module-attribute #
system = MessageBuilder('system')
Message #
MessageBuilder #
Source code in promplate/prompt/chat.py
ensure #
parse_chat_markup #
Source code in promplate/prompt/chat.py
promplate.prompt.template #
split_template_tokens module-attribute #
is_message_start module-attribute #
is_message_start = compile('<\\|\\s?(user|system|assistant)\\s?(\\w{1,64})?\\s?\\|>')
CodeBuilder #
Build source code conveniently.Source code in
promplate/prompt/builder.py
code instance-attribute #
indent_level instance-attribute #
indent_str instance-attribute #
__init__ #
__str__ #
add_line #
add_section #
indent #
dedent #
get_render_function #
get_render_function() -> FunctionType
Execute the code, and return a dict of globals it defines.Source code in
promplate/prompt/builder.py
AutoNaming #
Source code in promplate/prompt/utils.py
TemplateCore #
Bases: AutoNaming
A simple template compiler, for a jinja2-like syntax.Source code in
promplate/prompt/template.py 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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
class TemplateCore(AutoNaming):
"""A simple template compiler, for a jinja2-like syntax."""
def __init__(self, text: str):
"""Construct a Templite with the given `text`."""
self.text = text
def _flush(self):
for line in self._buffer:
self._builder.add_line(line)
self._buffer.clear()
@staticmethod
def _unwrap_token(token: str):
return dedent(token.strip()[2:-2].strip("-")).strip()
def _on_literal_token(self, token: str):
self._buffer.append(f"__append__({repr(token)})")
def _on_eval_token(self, token):
token = self._unwrap_token(token)
if "\n" in token:
mod = parse(token)
[*rest, last] = mod.body
assert isinstance(last, Expr), "{{ }} block must end with an expression, or you should use {# #} block"
self._buffer.extend(unparse(rest).splitlines()) # type: ignore
exp = unparse(last)
else:
exp = token
self._buffer.append(f"__append__({exp})")
def _on_exec_token(self, token):
self._buffer.extend(self._unwrap_token(token).splitlines())
def _on_special_token(self, token, sync: bool):
inner = self._unwrap_token(token)
if inner.startswith("end"):
last = self._ops_stack.pop()
assert last == inner.removeprefix("end")
self._flush()
self._builder.dedent()
else:
op = inner.split(" ", 1)[0]
if op == "if" or op == "for" or op == "while":
self._ops_stack.append(op)
self._flush()
self._builder.add_line(f"{inner}:")
self._builder.indent()
elif op == "else" or op == "elif":
self._flush()
self._builder.dedent()
self._builder.add_line(f"{inner}:")
self._builder.indent()
else:
params: str = self._make_context(inner)
if sync:
self._buffer.append(f"__append__({op}.render({params}))")
else:
self._buffer.append(f"__append__(await {op}.arender({params}))")
@staticmethod
def _make_context(text: str):
"""generate context parameter if specified otherwise use locals() by default"""
if version_info >= (3, 13):
return f"globals() | locals() | dict({text[text.index(' ') + 1:]})" if " " in text else "globals() | locals()"
return f"locals() | dict({text[text.index(' ') + 1:]})" if " " in text else "locals()"
def compile(self, sync=True, indent_str="\t"):
self._buffer = []
self._ops_stack = []
self._builder = get_base_builder(sync, indent_str)
for token in split_template_tokens(self.text):
if not token:
continue
s_token = token.strip()
if s_token.startswith("{{") and s_token.endswith("}}"):
self._on_eval_token(token)
elif s_token.startswith("{#") and s_token.endswith("#}"):
self._on_exec_token(token)
elif s_token.startswith("{%") and s_token.endswith("%}") and "\n" not in s_token:
self._on_special_token(token, sync)
else:
self._on_literal_token(token)
if self._ops_stack:
raise SyntaxError(self._ops_stack)
self._flush()
self._builder.add_line("return ''.join(map(str, __parts__))")
self._builder.dedent()
error_handling: Literal["linecache", "tempfile", "file"]
if version_info >= (3, 13):
error_handling = "linecache"
else:
error_handling = "tempfile" if __debug__ else "file"
def _patch_for_error_handling(self, sync: bool):
match self.error_handling:
case "linecache":
add_linecache(self.name, partial(self.get_script, sync, "\t"))
case "file" | "tempfile":
file = save_tempfile(self.name, self.get_script(sync, "\t"), self.error_handling == "tempfile")
sys_path.append(str(file.parent))
@cached_property
def _render_code(self):
self.compile()
return self._builder.get_render_function().__code__.replace(co_filename=self.name, co_name="render")
def render(self, context: Context) -> str:
try:
return eval(self._render_code, context)
except Exception:
self._patch_for_error_handling(sync=True)
raise
@cached_property
def _arender_code(self):
self.compile(sync=False)
return self._builder.get_render_function().__code__.replace(co_filename=self.name, co_name="arender")
async def arender(self, context: Context) -> str:
try:
return await eval(self._arender_code, context)
except Exception:
self._patch_for_error_handling(sync=False)
raise
def get_script(self, sync=True, indent_str=" "):
"""compile template string into python script"""
self.compile(sync, indent_str)
return str(self._builder)
text instance-attribute #
compile #
Source code in promplate/prompt/template.py
render #
arender async #
get_script #
Loader #
Bases: AutoNamingSource code in
promplate/prompt/template.py
aread async classmethod #
aread(path: str | Path, encoding='utf-8')
Source code in promplate/prompt/template.py
SafeChainMapContext #
Template #
Bases: TemplateCore, LoaderSource code in
promplate/prompt/template.py
get_base_builder #
Source code in promplate/prompt/builder.py
ensure_valid #
cache_once #
Source code in promplate/prompt/utils.py
get_builtins #
get_user_agent #
Source code in promplate/prompt/utils.py
add_linecache #
save_tempfile #
Source code in promplate/prompt/utils.py
promplate.prompt.utils #
split_template_tokens module-attribute #
is_message_start module-attribute #
is_message_start = compile('<\\|\\s?(user|system|assistant)\\s?(\\w{1,64})?\\s?\\|>')