banks 2.1.1__tar.gz → 2.1.2__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.
- {banks-2.1.1 → banks-2.1.2}/PKG-INFO +9 -3
- {banks-2.1.1 → banks-2.1.2}/README.md +8 -2
- {banks-2.1.1 → banks-2.1.2}/src/banks/__about__.py +1 -1
- {banks-2.1.1 → banks-2.1.2}/src/banks/extensions/chat.py +2 -4
- {banks-2.1.1 → banks-2.1.2}/src/banks/types.py +1 -1
- {banks-2.1.1 → banks-2.1.2}/tests/conftest.py +8 -0
- banks-2.1.2/tests/test_chat.py +82 -0
- banks-2.1.1/tests/test_chat.py +0 -29
- {banks-2.1.1 → banks-2.1.2}/.github/workflows/docs.yml +0 -0
- {banks-2.1.1 → banks-2.1.2}/.github/workflows/release.yml +0 -0
- {banks-2.1.1 → banks-2.1.2}/.github/workflows/test.yml +0 -0
- {banks-2.1.1 → banks-2.1.2}/.gitignore +0 -0
- {banks-2.1.1 → banks-2.1.2}/CITATION.cff +0 -0
- {banks-2.1.1 → banks-2.1.2}/CONTRIBUTING.md +0 -0
- {banks-2.1.1 → banks-2.1.2}/LICENSE.txt +0 -0
- {banks-2.1.1 → banks-2.1.2}/MANIFEST.in +0 -0
- {banks-2.1.1 → banks-2.1.2}/assets/banks.png +0 -0
- {banks-2.1.1 → banks-2.1.2}/cookbook/Prompt_Caching_with_Anthropic.ipynb +0 -0
- {banks-2.1.1 → banks-2.1.2}/cookbook/Prompt_Versioning.ipynb +0 -0
- {banks-2.1.1 → banks-2.1.2}/cookbook/in_prompt_completion.ipynb +0 -0
- {banks-2.1.1 → banks-2.1.2}/docs/config.md +0 -0
- {banks-2.1.1 → banks-2.1.2}/docs/examples.md +0 -0
- {banks-2.1.1 → banks-2.1.2}/docs/index.md +0 -0
- {banks-2.1.1 → banks-2.1.2}/docs/prompt.md +0 -0
- {banks-2.1.1 → banks-2.1.2}/docs/python.md +0 -0
- {banks-2.1.1 → banks-2.1.2}/docs/registry.md +0 -0
- {banks-2.1.1 → banks-2.1.2}/mkdocs.yml +0 -0
- {banks-2.1.1 → banks-2.1.2}/pyproject.toml +0 -0
- {banks-2.1.1 → banks-2.1.2}/src/banks/__init__.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/src/banks/cache.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/src/banks/config.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/src/banks/env.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/src/banks/errors.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/src/banks/extensions/__init__.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/src/banks/extensions/completion.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/src/banks/extensions/docs.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/src/banks/filters/__init__.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/src/banks/filters/audio.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/src/banks/filters/cache_control.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/src/banks/filters/image.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/src/banks/filters/lemmatize.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/src/banks/filters/tool.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/src/banks/prompt.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/src/banks/registries/__init__.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/src/banks/registries/directory.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/src/banks/registries/file.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/src/banks/registries/redis.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/src/banks/utils.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/tests/__init__.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/tests/data/1x1.png +0 -0
- {banks-2.1.1 → banks-2.1.2}/tests/data/empty.wav +0 -0
- {banks-2.1.1 → banks-2.1.2}/tests/e2e/__init__.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/tests/e2e/conftest.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/tests/e2e/test_completion.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/tests/e2e/test_function_calling.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/tests/templates/blog.jinja +0 -0
- {banks-2.1.1 → banks-2.1.2}/tests/templates/cache.jinja +0 -0
- {banks-2.1.1 → banks-2.1.2}/tests/templates/chat.jinja +0 -0
- {banks-2.1.1 → banks-2.1.2}/tests/templates/summarize.jinja +0 -0
- {banks-2.1.1 → banks-2.1.2}/tests/templates/summarize_lemma.jinja +0 -0
- {banks-2.1.1 → banks-2.1.2}/tests/test_audio.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/tests/test_cache.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/tests/test_cache_control.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/tests/test_completion.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/tests/test_config.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/tests/test_directory_registry.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/tests/test_file_registry.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/tests/test_image.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/tests/test_prompt.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/tests/test_redis_registry.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/tests/test_tool.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/tests/test_types.py +0 -0
- {banks-2.1.1 → banks-2.1.2}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: banks
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.2
|
|
4
4
|
Summary: A prompt programming language
|
|
5
5
|
Project-URL: Documentation, https://github.com/masci/banks#readme
|
|
6
6
|
Project-URL: Issues, https://github.com/masci/banks/issues
|
|
@@ -123,8 +123,14 @@ print(p.chat_messages({"persona": "helpful assistant"}))
|
|
|
123
123
|
|
|
124
124
|
# Output:
|
|
125
125
|
# [
|
|
126
|
-
# ChatMessage(role='system', content=
|
|
127
|
-
#
|
|
126
|
+
# ChatMessage(role='system', content=[
|
|
127
|
+
# ContentBlock(type=<ContentBlockType.text: 'text'>, cache_control=None, text='You are a helpful assistant.',
|
|
128
|
+
# image_url=None, input_audio=None)
|
|
129
|
+
# ], tool_call_id=None, name=None),
|
|
130
|
+
# ChatMessage(role='user', content=[
|
|
131
|
+
# ContentBlock(type=<ContentBlockType.text: 'text'>, cache_control=None, text='Hello, how are you?',
|
|
132
|
+
# image_url=None, input_audio=None)
|
|
133
|
+
# ], tool_call_id=None, name=None)
|
|
128
134
|
# ]
|
|
129
135
|
```
|
|
130
136
|
|
|
@@ -92,8 +92,14 @@ print(p.chat_messages({"persona": "helpful assistant"}))
|
|
|
92
92
|
|
|
93
93
|
# Output:
|
|
94
94
|
# [
|
|
95
|
-
# ChatMessage(role='system', content=
|
|
96
|
-
#
|
|
95
|
+
# ChatMessage(role='system', content=[
|
|
96
|
+
# ContentBlock(type=<ContentBlockType.text: 'text'>, cache_control=None, text='You are a helpful assistant.',
|
|
97
|
+
# image_url=None, input_audio=None)
|
|
98
|
+
# ], tool_call_id=None, name=None),
|
|
99
|
+
# ChatMessage(role='user', content=[
|
|
100
|
+
# ContentBlock(type=<ContentBlockType.text: 'text'>, cache_control=None, text='Hello, how are you?',
|
|
101
|
+
# image_url=None, input_audio=None)
|
|
102
|
+
# ], tool_call_id=None, name=None)
|
|
97
103
|
# ]
|
|
98
104
|
```
|
|
99
105
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# SPDX-FileCopyrightText: 2023-present Massimiliano Pippi <mpippi@gmail.com>
|
|
2
2
|
#
|
|
3
3
|
# SPDX-License-Identifier: MIT
|
|
4
|
-
import re
|
|
5
4
|
|
|
6
5
|
from jinja2 import TemplateSyntaxError, nodes
|
|
7
6
|
from jinja2.ext import Extension
|
|
@@ -9,7 +8,6 @@ from jinja2.ext import Extension
|
|
|
9
8
|
from banks.types import chat_message_from_text
|
|
10
9
|
|
|
11
10
|
SUPPORTED_TYPES = ("system", "user", "assistant")
|
|
12
|
-
CONTENT_BLOCK_REGEX = re.compile(r"<content_block>((?s:.)*)<\/content_block>")
|
|
13
11
|
|
|
14
12
|
|
|
15
13
|
class ChatExtension(Extension):
|
|
@@ -52,8 +50,8 @@ class ChatExtension(Extension):
|
|
|
52
50
|
raise TemplateSyntaxError(error_msg, lineno)
|
|
53
51
|
|
|
54
52
|
if attr_value.value not in SUPPORTED_TYPES:
|
|
55
|
-
types = ",".join(SUPPORTED_TYPES)
|
|
56
|
-
msg = f"Unknown role type '{attr_value}', use one of ({types})"
|
|
53
|
+
types = ", ".join(SUPPORTED_TYPES)
|
|
54
|
+
msg = f"Unknown role type '{attr_value.value}', use one of ({types})"
|
|
57
55
|
raise TemplateSyntaxError(msg, lineno)
|
|
58
56
|
|
|
59
57
|
# Pass the role name to the CallBlock node
|
|
@@ -16,7 +16,7 @@ from typing_extensions import Self
|
|
|
16
16
|
from .utils import parse_params_from_docstring, python_type_to_jsonschema
|
|
17
17
|
|
|
18
18
|
# pylint: disable=invalid-name
|
|
19
|
-
CONTENT_BLOCK_REGEX = re.compile(r"(<content_block>\{.*?\}<\/content_block>)|([^<](?:(?!<content_block>)
|
|
19
|
+
CONTENT_BLOCK_REGEX = re.compile(r"(<content_block>\{.*?\}<\/content_block>)|([^<](?:(?!<content_block>)[\s\S])*)")
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
class ContentBlockType(str, Enum):
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
1
3
|
import pytest
|
|
2
4
|
import redis
|
|
3
5
|
|
|
@@ -19,3 +21,9 @@ def skip_by_redis(request):
|
|
|
19
21
|
if request.node.get_closest_marker("redis"):
|
|
20
22
|
if not is_redis_available():
|
|
21
23
|
pytest.skip("Redis is not available")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@pytest.fixture
|
|
27
|
+
def data_path() -> Path:
|
|
28
|
+
here = Path(__file__).parent
|
|
29
|
+
return here / "data"
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
from typing import cast
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
from jinja2 import TemplateSyntaxError
|
|
5
|
+
|
|
6
|
+
from banks import Prompt
|
|
7
|
+
from banks.types import ContentBlock
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def test_wrong_tag():
|
|
11
|
+
with pytest.raises(TemplateSyntaxError):
|
|
12
|
+
Prompt("{% chat %}{% endchat %}")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_wrong_tag_params():
|
|
16
|
+
with pytest.raises(TemplateSyntaxError):
|
|
17
|
+
Prompt('{% chat foo="bar" %}{% endchat %}')
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def test_wrong_role_type():
|
|
21
|
+
with pytest.raises(TemplateSyntaxError):
|
|
22
|
+
Prompt('{% chat role="does not exist" %}{% endchat %}')
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def test_blocks():
|
|
26
|
+
p = Prompt('{% chat role="user" %}Tell me what you see: {{ picture | image }}{% endchat %}')
|
|
27
|
+
messages = p.chat_messages({"picture": "http://foo.bar"})
|
|
28
|
+
assert len(messages) == 1
|
|
29
|
+
content = messages[0].content
|
|
30
|
+
assert len(content) == 2
|
|
31
|
+
assert content[0].type == "text" # type: ignore
|
|
32
|
+
assert content[1].type == "image_url" # type: ignore
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def test_blocks_newlines():
|
|
36
|
+
p = Prompt("""{% chat role="system" %}
|
|
37
|
+
Some instructions:
|
|
38
|
+
|
|
39
|
+
1. Do this.
|
|
40
|
+
2. Then this.
|
|
41
|
+
3. Finally, that.
|
|
42
|
+
{% endchat %}""")
|
|
43
|
+
messages = p.chat_messages()
|
|
44
|
+
assert len(messages) == 1
|
|
45
|
+
assert len(messages[0].content) == 1
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def test_blocks_complex(data_path):
|
|
49
|
+
p = Prompt("""
|
|
50
|
+
{% chat role="system" %}
|
|
51
|
+
Given a list of images and text from each image, please answer the question to the best of your ability.
|
|
52
|
+
{% endchat %}
|
|
53
|
+
|
|
54
|
+
{% chat role="user" %}
|
|
55
|
+
{% for image_path, text in images_and_texts %}
|
|
56
|
+
Here is some text: {{ text }}
|
|
57
|
+
And here is an image:
|
|
58
|
+
{{ image_path | image }}
|
|
59
|
+
{% endfor %}
|
|
60
|
+
{% endchat %}
|
|
61
|
+
""")
|
|
62
|
+
|
|
63
|
+
messages = p.chat_messages(
|
|
64
|
+
{
|
|
65
|
+
"images_and_texts": [
|
|
66
|
+
(str(data_path / "1x1.png"), "This is the first page of the document"),
|
|
67
|
+
(str(data_path / "1x1.png"), "This is the second page of the document"),
|
|
68
|
+
]
|
|
69
|
+
}
|
|
70
|
+
)
|
|
71
|
+
assert len(messages) == 2
|
|
72
|
+
|
|
73
|
+
blocks = cast(list[ContentBlock], messages[0].content)
|
|
74
|
+
assert len(blocks) == 1
|
|
75
|
+
assert blocks[0].type == "text"
|
|
76
|
+
|
|
77
|
+
blocks = cast(list[ContentBlock], messages[1].content)
|
|
78
|
+
assert len(blocks) == 4
|
|
79
|
+
assert blocks[0].type == "text"
|
|
80
|
+
assert blocks[1].type == "image_url"
|
|
81
|
+
assert blocks[2].type == "text"
|
|
82
|
+
assert blocks[3].type == "image_url"
|
banks-2.1.1/tests/test_chat.py
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
from jinja2 import TemplateSyntaxError
|
|
3
|
-
|
|
4
|
-
from banks import Prompt
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def test_wrong_tag():
|
|
8
|
-
with pytest.raises(TemplateSyntaxError):
|
|
9
|
-
Prompt("{% chat %}{% endchat %}")
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def test_wrong_tag_params():
|
|
13
|
-
with pytest.raises(TemplateSyntaxError):
|
|
14
|
-
Prompt('{% chat foo="bar" %}{% endchat %}')
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def test_wrong_role_type():
|
|
18
|
-
with pytest.raises(TemplateSyntaxError):
|
|
19
|
-
Prompt('{% chat role="does not exist" %}{% endchat %}')
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def test_blocks():
|
|
23
|
-
p = Prompt('{% chat role="user" %}Tell me what you see: {{ picture | image }}{% endchat %}')
|
|
24
|
-
messages = p.chat_messages({"picture": "http://foo.bar"})
|
|
25
|
-
assert len(messages) == 1
|
|
26
|
-
content = messages[0].content
|
|
27
|
-
assert len(content) == 2
|
|
28
|
-
assert content[0].type == "text" # type: ignore
|
|
29
|
-
assert content[1].type == "image_url" # type: ignore
|
|
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
|
|
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
|
|
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
|
|
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
|