symbolicai 0.20.2__py3-none-any.whl → 1.0.0__py3-none-any.whl
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.
- symai/__init__.py +96 -64
- symai/backend/base.py +93 -80
- symai/backend/engines/drawing/engine_bfl.py +12 -11
- symai/backend/engines/drawing/engine_gpt_image.py +108 -87
- symai/backend/engines/embedding/engine_llama_cpp.py +25 -28
- symai/backend/engines/embedding/engine_openai.py +3 -5
- symai/backend/engines/execute/engine_python.py +6 -5
- symai/backend/engines/files/engine_io.py +74 -67
- symai/backend/engines/imagecaptioning/engine_blip2.py +3 -3
- symai/backend/engines/imagecaptioning/engine_llavacpp_client.py +54 -38
- symai/backend/engines/index/engine_pinecone.py +23 -24
- symai/backend/engines/index/engine_vectordb.py +16 -14
- symai/backend/engines/lean/engine_lean4.py +38 -34
- symai/backend/engines/neurosymbolic/__init__.py +41 -13
- symai/backend/engines/neurosymbolic/engine_anthropic_claudeX_chat.py +262 -182
- symai/backend/engines/neurosymbolic/engine_anthropic_claudeX_reasoning.py +263 -191
- symai/backend/engines/neurosymbolic/engine_deepseekX_reasoning.py +53 -49
- symai/backend/engines/neurosymbolic/engine_google_geminiX_reasoning.py +212 -211
- symai/backend/engines/neurosymbolic/engine_groq.py +87 -63
- symai/backend/engines/neurosymbolic/engine_huggingface.py +21 -24
- symai/backend/engines/neurosymbolic/engine_llama_cpp.py +117 -48
- symai/backend/engines/neurosymbolic/engine_openai_gptX_chat.py +256 -229
- symai/backend/engines/neurosymbolic/engine_openai_gptX_reasoning.py +270 -150
- symai/backend/engines/ocr/engine_apilayer.py +6 -8
- symai/backend/engines/output/engine_stdout.py +1 -4
- symai/backend/engines/search/engine_openai.py +7 -7
- symai/backend/engines/search/engine_perplexity.py +5 -5
- symai/backend/engines/search/engine_serpapi.py +12 -14
- symai/backend/engines/speech_to_text/engine_local_whisper.py +20 -27
- symai/backend/engines/symbolic/engine_wolframalpha.py +3 -3
- symai/backend/engines/text_to_speech/engine_openai.py +5 -7
- symai/backend/engines/text_vision/engine_clip.py +7 -11
- symai/backend/engines/userinput/engine_console.py +3 -3
- symai/backend/engines/webscraping/engine_requests.py +81 -48
- symai/backend/mixin/__init__.py +13 -0
- symai/backend/mixin/anthropic.py +4 -2
- symai/backend/mixin/deepseek.py +2 -0
- symai/backend/mixin/google.py +2 -0
- symai/backend/mixin/openai.py +11 -3
- symai/backend/settings.py +83 -16
- symai/chat.py +101 -78
- symai/collect/__init__.py +7 -1
- symai/collect/dynamic.py +77 -69
- symai/collect/pipeline.py +35 -27
- symai/collect/stats.py +75 -63
- symai/components.py +198 -169
- symai/constraints.py +15 -12
- symai/core.py +698 -359
- symai/core_ext.py +32 -34
- symai/endpoints/api.py +80 -73
- symai/extended/.DS_Store +0 -0
- symai/extended/__init__.py +46 -12
- symai/extended/api_builder.py +11 -8
- symai/extended/arxiv_pdf_parser.py +13 -12
- symai/extended/bibtex_parser.py +2 -3
- symai/extended/conversation.py +101 -90
- symai/extended/document.py +17 -10
- symai/extended/file_merger.py +18 -13
- symai/extended/graph.py +18 -13
- symai/extended/html_style_template.py +2 -4
- symai/extended/interfaces/blip_2.py +1 -2
- symai/extended/interfaces/clip.py +1 -2
- symai/extended/interfaces/console.py +7 -1
- symai/extended/interfaces/dall_e.py +1 -1
- symai/extended/interfaces/flux.py +1 -1
- symai/extended/interfaces/gpt_image.py +1 -1
- symai/extended/interfaces/input.py +1 -1
- symai/extended/interfaces/llava.py +0 -1
- symai/extended/interfaces/naive_vectordb.py +7 -8
- symai/extended/interfaces/naive_webscraping.py +1 -1
- symai/extended/interfaces/ocr.py +1 -1
- symai/extended/interfaces/pinecone.py +6 -5
- symai/extended/interfaces/serpapi.py +1 -1
- symai/extended/interfaces/terminal.py +2 -3
- symai/extended/interfaces/tts.py +1 -1
- symai/extended/interfaces/whisper.py +1 -1
- symai/extended/interfaces/wolframalpha.py +1 -1
- symai/extended/metrics/__init__.py +11 -1
- symai/extended/metrics/similarity.py +11 -13
- symai/extended/os_command.py +17 -16
- symai/extended/packages/__init__.py +29 -3
- symai/extended/packages/symdev.py +19 -16
- symai/extended/packages/sympkg.py +12 -9
- symai/extended/packages/symrun.py +21 -19
- symai/extended/repo_cloner.py +11 -10
- symai/extended/seo_query_optimizer.py +1 -2
- symai/extended/solver.py +20 -23
- symai/extended/summarizer.py +4 -3
- symai/extended/taypan_interpreter.py +10 -12
- symai/extended/vectordb.py +99 -82
- symai/formatter/__init__.py +9 -1
- symai/formatter/formatter.py +12 -16
- symai/formatter/regex.py +62 -63
- symai/functional.py +176 -122
- symai/imports.py +136 -127
- symai/interfaces.py +56 -27
- symai/memory.py +14 -13
- symai/misc/console.py +49 -39
- symai/misc/loader.py +5 -3
- symai/models/__init__.py +17 -1
- symai/models/base.py +269 -181
- symai/models/errors.py +0 -1
- symai/ops/__init__.py +32 -22
- symai/ops/measures.py +11 -15
- symai/ops/primitives.py +348 -228
- symai/post_processors.py +32 -28
- symai/pre_processors.py +39 -41
- symai/processor.py +6 -4
- symai/prompts.py +59 -45
- symai/server/huggingface_server.py +23 -20
- symai/server/llama_cpp_server.py +7 -5
- symai/shell.py +3 -4
- symai/shellsv.py +499 -375
- symai/strategy.py +517 -287
- symai/symbol.py +111 -116
- symai/utils.py +42 -36
- {symbolicai-0.20.2.dist-info → symbolicai-1.0.0.dist-info}/METADATA +4 -2
- symbolicai-1.0.0.dist-info/RECORD +163 -0
- symbolicai-0.20.2.dist-info/RECORD +0 -162
- {symbolicai-0.20.2.dist-info → symbolicai-1.0.0.dist-info}/WHEEL +0 -0
- {symbolicai-0.20.2.dist-info → symbolicai-1.0.0.dist-info}/entry_points.txt +0 -0
- {symbolicai-0.20.2.dist-info → symbolicai-1.0.0.dist-info}/licenses/LICENSE +0 -0
- {symbolicai-0.20.2.dist-info → symbolicai-1.0.0.dist-info}/top_level.txt +0 -0
|
@@ -7,7 +7,7 @@ import openai
|
|
|
7
7
|
|
|
8
8
|
from ....components import SelfPrompt
|
|
9
9
|
from ....core_ext import retry
|
|
10
|
-
from ....utils import
|
|
10
|
+
from ....utils import UserMessage
|
|
11
11
|
from ...base import Engine
|
|
12
12
|
from ...settings import SYMAI_CONFIG
|
|
13
13
|
|
|
@@ -18,6 +18,15 @@ logging.getLogger("httpx").setLevel(logging.ERROR)
|
|
|
18
18
|
logging.getLogger("httpcore").setLevel(logging.ERROR)
|
|
19
19
|
|
|
20
20
|
|
|
21
|
+
_NON_VERBOSE_OUTPUT = (
|
|
22
|
+
"<META_INSTRUCTION/>\n"
|
|
23
|
+
"You do not output anything else, like verbose preambles or post explanation, such as "
|
|
24
|
+
"\"Sure, let me...\", \"Hope that was helpful...\", \"Yes, I can help you with that...\", etc. "
|
|
25
|
+
"Consider well formatted output, e.g. for sentences use punctuation, spaces etc. or for code use "
|
|
26
|
+
"indentation, etc. Never add meta instructions information to your output!\n\n"
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
|
|
21
30
|
class GroqEngine(Engine):
|
|
22
31
|
def __init__(self, api_key: str | None = None, model: str | None = None):
|
|
23
32
|
super().__init__()
|
|
@@ -36,7 +45,7 @@ class GroqEngine(Engine):
|
|
|
36
45
|
try:
|
|
37
46
|
self.client = openai.OpenAI(api_key=openai.api_key, base_url="https://api.groq.com/openai/v1")
|
|
38
47
|
except Exception as e:
|
|
39
|
-
|
|
48
|
+
UserMessage(f'Failed to initialize OpenAI client. Please check your OpenAI library version. Caused by: {e}', raise_with=ValueError)
|
|
40
49
|
|
|
41
50
|
def id(self) -> str:
|
|
42
51
|
if self.config.get('NEUROSYMBOLIC_ENGINE_MODEL') and \
|
|
@@ -53,11 +62,11 @@ class GroqEngine(Engine):
|
|
|
53
62
|
if 'seed' in kwargs:
|
|
54
63
|
self.seed = kwargs['seed']
|
|
55
64
|
|
|
56
|
-
def compute_required_tokens(self,
|
|
57
|
-
|
|
65
|
+
def compute_required_tokens(self, _messages):
|
|
66
|
+
UserMessage("Token counting not implemented for this engine.", raise_with=NotImplementedError)
|
|
58
67
|
|
|
59
|
-
def compute_remaining_tokens(self,
|
|
60
|
-
|
|
68
|
+
def compute_remaining_tokens(self, _prompts: list) -> int:
|
|
69
|
+
UserMessage("Token counting not implemented for this engine.", raise_with=NotImplementedError)
|
|
61
70
|
|
|
62
71
|
def _handle_prefix(self, model_name: str) -> str:
|
|
63
72
|
"""Handle prefix for model name."""
|
|
@@ -82,7 +91,7 @@ class GroqEngine(Engine):
|
|
|
82
91
|
thinking_content = None
|
|
83
92
|
|
|
84
93
|
cleaned_content = re.sub(think_pattern, '', content, flags=re.DOTALL).strip()
|
|
85
|
-
cleaned_output = [cleaned_content
|
|
94
|
+
cleaned_output = [cleaned_content, *output[1:]]
|
|
86
95
|
|
|
87
96
|
return thinking_content, cleaned_output
|
|
88
97
|
|
|
@@ -100,9 +109,9 @@ class GroqEngine(Engine):
|
|
|
100
109
|
except Exception as e:
|
|
101
110
|
if openai.api_key is None or openai.api_key == '':
|
|
102
111
|
msg = 'Groq API key is not set. Please set it in the config file or pass it as an argument to the command method.'
|
|
103
|
-
|
|
112
|
+
UserMessage(msg)
|
|
104
113
|
if self.config['NEUROSYMBOLIC_ENGINE_API_KEY'] is None or self.config['NEUROSYMBOLIC_ENGINE_API_KEY'] == '':
|
|
105
|
-
|
|
114
|
+
UserMessage(msg, raise_with=ValueError)
|
|
106
115
|
openai.api_key = self.config['NEUROSYMBOLIC_ENGINE_API_KEY']
|
|
107
116
|
|
|
108
117
|
callback = self.client.chat.completions.create
|
|
@@ -111,7 +120,7 @@ class GroqEngine(Engine):
|
|
|
111
120
|
if except_remedy is not None:
|
|
112
121
|
res = except_remedy(self, e, callback, argument)
|
|
113
122
|
else:
|
|
114
|
-
|
|
123
|
+
UserMessage(f'Error during generation. Caused by: {e}', raise_with=ValueError)
|
|
115
124
|
|
|
116
125
|
metadata = {'raw_output': res}
|
|
117
126
|
if payload.get('tools'):
|
|
@@ -126,11 +135,11 @@ class GroqEngine(Engine):
|
|
|
126
135
|
|
|
127
136
|
def _prepare_raw_input(self, argument):
|
|
128
137
|
if not argument.prop.processed_input:
|
|
129
|
-
|
|
138
|
+
UserMessage('Need to provide a prompt instruction to the engine if raw_input is enabled.', raise_with=ValueError)
|
|
130
139
|
value = argument.prop.processed_input
|
|
131
140
|
# convert to dict if not already
|
|
132
|
-
if
|
|
133
|
-
if
|
|
141
|
+
if not isinstance(value, list):
|
|
142
|
+
if not isinstance(value, dict):
|
|
134
143
|
value = {'role': 'user', 'content': str(value)}
|
|
135
144
|
value = [value]
|
|
136
145
|
return value
|
|
@@ -139,18 +148,32 @@ class GroqEngine(Engine):
|
|
|
139
148
|
if argument.prop.raw_input:
|
|
140
149
|
argument.prop.prepared_input = self._prepare_raw_input(argument)
|
|
141
150
|
return
|
|
151
|
+
self._validate_response_format(argument)
|
|
142
152
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
153
|
+
system = self._build_system_message(argument)
|
|
154
|
+
user_content = self._build_user_content(argument)
|
|
155
|
+
user_prompt = {"role": "user", "content": user_content}
|
|
156
|
+
system, user_prompt = self._apply_self_prompt_if_needed(argument, system, user_prompt)
|
|
146
157
|
|
|
147
|
-
|
|
148
|
-
system
|
|
149
|
-
|
|
158
|
+
argument.prop.prepared_input = [
|
|
159
|
+
{ "role": "system", "content": system },
|
|
160
|
+
user_prompt,
|
|
161
|
+
]
|
|
150
162
|
|
|
163
|
+
def _validate_response_format(self, argument) -> None:
|
|
151
164
|
if argument.prop.response_format:
|
|
152
|
-
|
|
153
|
-
assert
|
|
165
|
+
response_format = argument.prop.response_format
|
|
166
|
+
assert response_format.get('type') is not None, (
|
|
167
|
+
'Expected format `{ "type": "json_object" }`! We are using the OpenAI compatible API for Groq. '
|
|
168
|
+
"See more here: https://console.groq.com/docs/tool-use"
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
def _build_system_message(self, argument) -> str:
|
|
172
|
+
system: str = ""
|
|
173
|
+
if argument.prop.suppress_verbose_output:
|
|
174
|
+
system += _NON_VERBOSE_OUTPUT
|
|
175
|
+
if system:
|
|
176
|
+
system = f"{system}\n"
|
|
154
177
|
|
|
155
178
|
ref = argument.prop.instance
|
|
156
179
|
static_ctxt, dyn_ctxt = ref.global_context
|
|
@@ -160,62 +183,61 @@ class GroqEngine(Engine):
|
|
|
160
183
|
if len(dyn_ctxt) > 0:
|
|
161
184
|
system += f"<DYNAMIC CONTEXT/>\n{dyn_ctxt}\n\n"
|
|
162
185
|
|
|
163
|
-
payload = argument.prop.payload
|
|
164
186
|
if argument.prop.payload:
|
|
165
|
-
system += f"<ADDITIONAL CONTEXT/>\n{
|
|
187
|
+
system += f"<ADDITIONAL CONTEXT/>\n{argument.prop.payload!s}\n\n"
|
|
166
188
|
|
|
167
189
|
examples = argument.prop.examples
|
|
168
190
|
if examples and len(examples) > 0:
|
|
169
|
-
system += f"<EXAMPLES/>\n{
|
|
191
|
+
system += f"<EXAMPLES/>\n{examples!s}\n\n"
|
|
170
192
|
|
|
171
193
|
if argument.prop.prompt is not None and len(argument.prop.prompt) > 0:
|
|
172
194
|
val = str(argument.prop.prompt)
|
|
173
195
|
system += f"<INSTRUCTION/>\n{val}\n\n"
|
|
174
196
|
|
|
175
|
-
suffix: str = str(argument.prop.processed_input)
|
|
176
|
-
user += f"{suffix}"
|
|
177
|
-
|
|
178
197
|
if argument.prop.template_suffix:
|
|
179
|
-
system +=
|
|
198
|
+
system += (
|
|
199
|
+
" You will only generate content for the placeholder "
|
|
200
|
+
f"`{argument.prop.template_suffix!s}` following the instructions and the provided context information.\n\n"
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
return system
|
|
180
204
|
|
|
181
|
-
|
|
205
|
+
def _build_user_content(self, argument) -> str:
|
|
206
|
+
return str(argument.prop.processed_input)
|
|
182
207
|
|
|
183
|
-
|
|
208
|
+
def _apply_self_prompt_if_needed(self, argument, system, user_prompt):
|
|
184
209
|
if argument.prop.instance._kwargs.get('self_prompt', False) or argument.prop.self_prompt:
|
|
185
210
|
self_prompter = SelfPrompt()
|
|
186
|
-
|
|
187
|
-
res = self_prompter({'user': user, 'system': system})
|
|
211
|
+
res = self_prompter({'user': user_prompt['content'], 'system': system})
|
|
188
212
|
if res is None:
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
system = res['system']
|
|
193
|
-
|
|
194
|
-
argument.prop.prepared_input = [
|
|
195
|
-
{ "role": "system", "content": system },
|
|
196
|
-
user_prompt,
|
|
197
|
-
]
|
|
213
|
+
UserMessage("Self-prompting failed!", raise_with=ValueError)
|
|
214
|
+
return res['system'], {"role": "user", "content": res['user']}
|
|
215
|
+
return system, user_prompt
|
|
198
216
|
|
|
199
217
|
def _process_function_calls(self, res, metadata):
|
|
200
218
|
hit = False
|
|
201
|
-
if
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
+
if (
|
|
220
|
+
hasattr(res, 'choices')
|
|
221
|
+
and res.choices
|
|
222
|
+
and hasattr(res.choices[0], 'message')
|
|
223
|
+
and res.choices[0].message
|
|
224
|
+
and hasattr(res.choices[0].message, 'tool_calls')
|
|
225
|
+
and res.choices[0].message.tool_calls
|
|
226
|
+
):
|
|
227
|
+
for tool_call in res.choices[0].message.tool_calls:
|
|
228
|
+
if hasattr(tool_call, 'function') and tool_call.function:
|
|
229
|
+
if hit:
|
|
230
|
+
UserMessage("Multiple function calls detected in the response but only the first one will be processed.")
|
|
231
|
+
break
|
|
232
|
+
try:
|
|
233
|
+
args_dict = json.loads(tool_call.function.arguments)
|
|
234
|
+
except json.JSONDecodeError:
|
|
235
|
+
args_dict = {}
|
|
236
|
+
metadata['function_call'] = {
|
|
237
|
+
'name': tool_call.function.name,
|
|
238
|
+
'arguments': args_dict
|
|
239
|
+
}
|
|
240
|
+
hit = True
|
|
219
241
|
return metadata
|
|
220
242
|
|
|
221
243
|
def _prepare_request_payload(self, messages, argument):
|
|
@@ -231,12 +253,12 @@ class GroqEngine(Engine):
|
|
|
231
253
|
"stream_options",
|
|
232
254
|
]:
|
|
233
255
|
if param in kwargs:
|
|
234
|
-
|
|
256
|
+
UserMessage(f"The parameter {param} is not supported by the Groq API. It will be ignored.")
|
|
235
257
|
del kwargs[param]
|
|
236
258
|
|
|
237
259
|
n = kwargs.get('n', 1)
|
|
238
260
|
if n > 1:
|
|
239
|
-
|
|
261
|
+
UserMessage("If N is supplied, it must be equal to 1. We default to 1 to not crash your program.")
|
|
240
262
|
n = 1
|
|
241
263
|
|
|
242
264
|
# Handle Groq JSON-mode quirk: JSON Object Mode internally uses a constrainer tool.
|
|
@@ -244,8 +266,10 @@ class GroqEngine(Engine):
|
|
|
244
266
|
tool_choice = kwargs.get('tool_choice', 'auto' if kwargs.get('tools') else 'none')
|
|
245
267
|
tools = kwargs.get('tools')
|
|
246
268
|
if response_format and isinstance(response_format, dict) and response_format.get('type') == 'json_object':
|
|
247
|
-
if tool_choice in (None, 'none'):
|
|
248
|
-
|
|
269
|
+
if tool_choice in (None, 'none'):
|
|
270
|
+
tool_choice = 'auto'
|
|
271
|
+
if tools:
|
|
272
|
+
tools = None
|
|
249
273
|
|
|
250
274
|
payload = {
|
|
251
275
|
"messages": messages,
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
import json
|
|
2
1
|
import logging
|
|
3
|
-
import re
|
|
4
2
|
from copy import deepcopy
|
|
5
|
-
from typing import List, Optional
|
|
6
3
|
|
|
7
4
|
import requests
|
|
8
5
|
|
|
9
|
-
from ....utils import
|
|
6
|
+
from ....utils import UserMessage
|
|
10
7
|
from ...base import Engine
|
|
11
8
|
from ...settings import SYMAI_CONFIG, SYMSERVER_CONFIG
|
|
12
9
|
|
|
@@ -20,28 +17,28 @@ class HFTokenizer:
|
|
|
20
17
|
_server_endpoint = f"http://{SYMSERVER_CONFIG.get('host')}:{SYMSERVER_CONFIG.get('port')}"
|
|
21
18
|
|
|
22
19
|
@staticmethod
|
|
23
|
-
def encode(text: str, add_special_tokens: bool = False) ->
|
|
20
|
+
def encode(text: str, add_special_tokens: bool = False) -> list[int]:
|
|
24
21
|
res = requests.post(f"{HFTokenizer._server_endpoint}/tokenize", json={
|
|
25
22
|
"input": text,
|
|
26
23
|
"add_special_tokens": add_special_tokens,
|
|
27
24
|
})
|
|
28
25
|
|
|
29
26
|
if res.status_code != 200:
|
|
30
|
-
|
|
27
|
+
UserMessage(f"Request failed with status code: {res.status_code}", raise_with=ValueError)
|
|
31
28
|
|
|
32
29
|
res = res.json()
|
|
33
30
|
|
|
34
31
|
return res['tokens']
|
|
35
32
|
|
|
36
33
|
@staticmethod
|
|
37
|
-
def decode(tokens:
|
|
34
|
+
def decode(tokens: list[int], skip_special_tokens: bool = True) -> str:
|
|
38
35
|
res = requests.post(f"{HFTokenizer._server_endpoint}/detokenize", json={
|
|
39
36
|
"tokens": tokens,
|
|
40
37
|
"skip_special_tokens": skip_special_tokens,
|
|
41
38
|
})
|
|
42
39
|
|
|
43
40
|
if res.status_code != 200:
|
|
44
|
-
|
|
41
|
+
UserMessage(f"Request failed with status code: {res.status_code}", raise_with=ValueError)
|
|
45
42
|
|
|
46
43
|
res = res.json()
|
|
47
44
|
|
|
@@ -49,7 +46,7 @@ class HFTokenizer:
|
|
|
49
46
|
|
|
50
47
|
|
|
51
48
|
class HFEngine(Engine):
|
|
52
|
-
def __init__(self, model:
|
|
49
|
+
def __init__(self, model: str | None = None):
|
|
53
50
|
super().__init__()
|
|
54
51
|
self.config = deepcopy(SYMAI_CONFIG)
|
|
55
52
|
# In case we use EngineRepository.register to inject the api_key and model => dynamically change the engine at runtime
|
|
@@ -58,7 +55,7 @@ class HFEngine(Engine):
|
|
|
58
55
|
if self.id() != 'neurosymbolic':
|
|
59
56
|
return
|
|
60
57
|
if not SYMSERVER_CONFIG.get('online'):
|
|
61
|
-
|
|
58
|
+
UserMessage('You are using the huggingface engine, but the server endpoint is not started. Please start the server with `symserver [--args]` or run `symserver --help` to see the available options for this engine.', raise_with=ValueError)
|
|
62
59
|
self.server_endpoint = f"http://{SYMSERVER_CONFIG.get('host')}:{SYMSERVER_CONFIG.get('port')}"
|
|
63
60
|
self.tokenizer = HFTokenizer # backwards compatibility with how we handle tokenization, i.e. self.tokenizer().encode(...)
|
|
64
61
|
self.name = self.__class__.__name__
|
|
@@ -77,10 +74,10 @@ class HFEngine(Engine):
|
|
|
77
74
|
if 'except_remedy' in kwargs:
|
|
78
75
|
self.except_remedy = kwargs['except_remedy']
|
|
79
76
|
|
|
80
|
-
def compute_required_tokens(self,
|
|
81
|
-
|
|
82
|
-
def compute_remaining_tokens(self,
|
|
83
|
-
|
|
77
|
+
def compute_required_tokens(self, _messages) -> int:
|
|
78
|
+
UserMessage('Not implemented for HFEngine. Please use the tokenizer directly to compute tokens.', raise_with=NotImplementedError)
|
|
79
|
+
def compute_remaining_tokens(self, _prompts: list) -> int:
|
|
80
|
+
UserMessage('Not implemented for HFEngine. Please use the tokenizer directly to compute tokens.', raise_with=NotImplementedError)
|
|
84
81
|
def forward(self, argument):
|
|
85
82
|
kwargs = argument.kwargs
|
|
86
83
|
prompts = argument.prop.prepared_input
|
|
@@ -117,7 +114,7 @@ class HFEngine(Engine):
|
|
|
117
114
|
})
|
|
118
115
|
|
|
119
116
|
if res.status_code != 200:
|
|
120
|
-
|
|
117
|
+
UserMessage(f"Request failed with status code: {res.status_code}", raise_with=ValueError)
|
|
121
118
|
|
|
122
119
|
res = res.json()
|
|
123
120
|
|
|
@@ -125,7 +122,7 @@ class HFEngine(Engine):
|
|
|
125
122
|
if except_remedy is not None:
|
|
126
123
|
res = except_remedy(self, e, argument)
|
|
127
124
|
else:
|
|
128
|
-
|
|
125
|
+
UserMessage(f'Error during generation. Caused by: {e}', raise_with=ValueError)
|
|
129
126
|
|
|
130
127
|
metadata = {'raw_output': res}
|
|
131
128
|
|
|
@@ -135,10 +132,10 @@ class HFEngine(Engine):
|
|
|
135
132
|
|
|
136
133
|
def _prepare_raw_input(self, argument):
|
|
137
134
|
if not argument.prop.processed_input:
|
|
138
|
-
|
|
135
|
+
UserMessage('Need to provide a prompt instruction to the engine if raw_input is enabled.', raise_with=ValueError)
|
|
139
136
|
value = argument.prop.processed_input
|
|
140
|
-
if
|
|
141
|
-
if
|
|
137
|
+
if not isinstance(value, list):
|
|
138
|
+
if not isinstance(value, dict):
|
|
142
139
|
value = {'role': 'user', 'content': str(value)}
|
|
143
140
|
value = [value]
|
|
144
141
|
return value
|
|
@@ -167,17 +164,17 @@ class HFEngine(Engine):
|
|
|
167
164
|
|
|
168
165
|
payload = argument.prop.payload
|
|
169
166
|
if argument.prop.payload:
|
|
170
|
-
user += f"<ADDITIONAL_CONTEXT/>\n{
|
|
167
|
+
user += f"<ADDITIONAL_CONTEXT/>\n{payload!s}\n\n"
|
|
171
168
|
|
|
172
|
-
examples:
|
|
169
|
+
examples: list[str] = argument.prop.examples
|
|
173
170
|
if examples and len(examples) > 0:
|
|
174
|
-
user += f"<EXAMPLES/>\n{
|
|
171
|
+
user += f"<EXAMPLES/>\n{examples!s}\n\n"
|
|
175
172
|
|
|
176
173
|
if argument.prop.prompt is not None and len(argument.prop.prompt) > 0:
|
|
177
|
-
user += f"<INSTRUCTION/>\n{
|
|
174
|
+
user += f"<INSTRUCTION/>\n{argument.prop.prompt!s}\n\n"
|
|
178
175
|
|
|
179
176
|
if argument.prop.template_suffix:
|
|
180
|
-
user += f" You will only generate content for the placeholder `{
|
|
177
|
+
user += f" You will only generate content for the placeholder `{argument.prop.template_suffix!s}` following the instructions and the provided context information.\n\n"
|
|
181
178
|
|
|
182
179
|
user += str(argument.prop.processed_input)
|
|
183
180
|
|