exploring-machine 0.0.1__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.
@@ -0,0 +1,127 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Python
3
+
4
+ """Copyright (c) Alexander Fedotov.
5
+ This source code is licensed under the license found in the
6
+ LICENSE file in the root directory of this source tree.
7
+ """
8
+ import urllib.request
9
+ import urllib.error
10
+ import urllib.parse
11
+ import json
12
+ from os import environ
13
+ from ..utilities import messages_to_mpj
14
+
15
+
16
+ def respond(messages=None, instructions=None, **kwargs):
17
+ """
18
+ """
19
+ api_key = environ.get('GEMINI_API_KEY', '')
20
+ api_base = environ.get('GEMINI_API_BASE', 'https://generativelanguage.googleapis.com/v1beta')
21
+ content_model = environ.get('GEMINI_DEFAULT_CONTENT_MODEL', 'gemma-4-31b-it')
22
+
23
+ garbage = [
24
+ {'category': 'HARM_CATEGORY_HATE_SPEECH', 'threshold': 'BLOCK_NONE'},
25
+ {'category': 'HARM_CATEGORY_SEXUALLY_EXPLICIT', 'threshold': 'BLOCK_NONE'},
26
+ {'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', 'threshold': 'BLOCK_NONE'},
27
+ {'category': 'HARM_CATEGORY_HARASSMENT', 'threshold': 'BLOCK_NONE'},
28
+ {'category': 'HARM_CATEGORY_CIVIC_INTEGRITY', 'threshold': 'BLOCK_NONE'}
29
+ ]
30
+
31
+ instructions = kwargs.get('system_instruction', instructions)
32
+ system_instruction = dict(role='system', parts=[dict(text=instructions)]) if instructions else None
33
+
34
+ # Trickery for thinking models
35
+ thinking_config = None
36
+ model = kwargs.get("model", content_model)
37
+ if model.startswith('gemini-2.5'):
38
+ thinking_config = {
39
+ 'includeThoughts': kwargs.get('include_thoughts', True),
40
+ 'thinkingBudget': kwargs.get('thinking_budget', 10000)
41
+ }
42
+ elif model.startswith('gemini-3'):
43
+ thinking_config = {
44
+ 'includeThoughts': kwargs.get('include_thoughts', True),
45
+ 'thinkingLevel': kwargs.get('thinking_level', 'high')
46
+ }
47
+ elif model.startswith('gemma-4'):
48
+ thinking_config = {
49
+ 'includeThoughts': kwargs.get('include_thoughts', True)
50
+ }
51
+
52
+ # Define the payload
53
+ payload = {
54
+ 'systemInstruction': system_instruction,
55
+ 'contents': messages,
56
+ 'safetySettings': garbage,
57
+ 'generationConfig': {
58
+ 'stopSequences': kwargs.get('stop_sequences', ['STOP', 'Title']),
59
+ 'responseMimeType': kwargs.get('mime_type', 'text/plain'),
60
+ 'responseModalities': kwargs.get('modalities', ['TEXT']),
61
+ 'temperature': kwargs.get('temperature', 1.0),
62
+ 'maxOutputTokens': kwargs.get('max_tokens', 10000),
63
+ 'topP': kwargs.get('top_p', 0.9),
64
+ 'topK': kwargs.get('top_k', 10),
65
+ 'enableEnhancedCivicAnswers': False,
66
+ },
67
+ }
68
+ if thinking_config:
69
+ payload['generationConfig']['thinkingConfig'] = thinking_config
70
+ if kwargs.get('sources'):
71
+ payload['tools'].append(
72
+ {
73
+ "url_context": {}
74
+ }
75
+ )
76
+
77
+ # Convert data dictionary to JSON and encode it to bytes
78
+ data_bytes = json.dumps(payload).encode('utf-8')
79
+
80
+ # Set the mandatory headers
81
+ headers = {
82
+ "Content-Type": "application/json",
83
+ "User-Agent": "Exploring-Machine"
84
+ }
85
+
86
+ # urlencode parameter
87
+ params = urllib.parse.urlencode({'key': api_key})
88
+
89
+ # Create the Request object
90
+ req = urllib.request.Request(
91
+ f'{api_base}/models/{kwargs.get("model", content_model)}:generateContent?{params}',
92
+ data=data_bytes,
93
+ headers=headers,
94
+ method="POST")
95
+
96
+ try:
97
+ # Execute the request
98
+ with urllib.request.urlopen(req, timeout=300) as response:
99
+ response_data = response.read().decode('utf-8')
100
+ output = json.loads(response_data)
101
+ text = ''
102
+ thoughts = ''
103
+ if output['candidates'][0]['finishReason'] == 'SAFETY':
104
+ raise Exception('Answer censored by Google.')
105
+ for part in output['candidates'][0]['content']['parts']:
106
+ if part.get('thought'):
107
+ thoughts += part['text']
108
+ else:
109
+ text += part['text']
110
+
111
+ return thoughts, text
112
+
113
+ except urllib.error.HTTPError as e:
114
+ # Handle HTTP errors (e.g., 401 Unauthorized, 400 Bad Request)
115
+ error_info = e.read().decode('utf-8', errors='ignore')
116
+ print(f"HTTP Error {e.code}: {e.reason}")
117
+ print(f"Error Details: {error_info}")
118
+ return '', ''
119
+
120
+ except urllib.error.URLError as e:
121
+ # Handle network/connection errors
122
+ print(f"Failed to reach the server: {e.reason}")
123
+ return '', ''
124
+
125
+
126
+ if __name__ == '__main__':
127
+ ...
@@ -0,0 +1,86 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Python
3
+
4
+ """Copyright (c) Alexander Fedotov.
5
+ This source code is licensed under the license found in the
6
+ LICENSE file in the root directory of this source tree.
7
+ """
8
+ import json
9
+ import urllib.request
10
+ import urllib.error
11
+ from os import environ
12
+
13
+
14
+ def respond(messages=None, instructions=None, **kwargs):
15
+ """ All parameters should be in kwargs, but they are optional
16
+ """
17
+ # The configuration.
18
+ api_key = environ.get("CHINF_API_KEY", '')
19
+ default_model = environ.get("CHINF_DEFAULT_MODEL", 'gpt-5.6-luna')
20
+ api_base = environ.get("CHINF_API_BASE", "https://api.cheaperinference.com/v1")
21
+
22
+ # Set the mandatory headers
23
+ headers = {
24
+ "Content-Type": "application/json",
25
+ "Authorization": f"Bearer {api_key}",
26
+ "X-Api-Key": api_key,
27
+ "Anthropic-Version": "2023-06-01",
28
+ "User-Agent": "chinf"
29
+ }
30
+
31
+ # Receive the instruction
32
+ instruction = kwargs.get('system_instruction', instructions)
33
+ first_message = [dict(role='system', content=instruction)] if instruction else []
34
+
35
+ # add contents and user text to the first (instruction) message
36
+ first_message.extend(messages)
37
+ instruction_and_contents = first_message
38
+
39
+ # Define the initial payload
40
+ payload = {
41
+ "model": kwargs.get("model", default_model),
42
+ "messages": instruction_and_contents,
43
+ "max_tokens": kwargs.get("max_tokens", 132000),
44
+ "reasoning_effort": "max",
45
+ }
46
+ # Convert
47
+ data_bytes = json.dumps(payload).encode('utf-8')
48
+ # Create the Request object
49
+ req = urllib.request.Request(
50
+ f'{api_base}/chat/completions',
51
+ data=data_bytes,
52
+ headers=headers,
53
+ method="POST")
54
+ # Try to query
55
+ try:
56
+ # Execute the request
57
+ with urllib.request.urlopen(req, timeout=3000) as response:
58
+ response_data = response.read().decode('utf-8')
59
+ output = json.loads(response_data)
60
+
61
+ except urllib.error.HTTPError as e:
62
+ # Handle HTTP errors (e.g., 401 Unauthorized, 400 Bad Request)
63
+ error_info = e.read().decode('utf-8', errors='ignore')
64
+ print(f"HTTP Error {e.code}: {e.reason}")
65
+ print(f"Error Details: {error_info}")
66
+ output = {}
67
+
68
+ except urllib.error.URLError as e:
69
+ # Handle network/connection errors
70
+ print(f"Failed to reach the server: {e.reason}")
71
+ output = {}
72
+ # Discern what we got
73
+ result = output.get('choices', {})
74
+ if result:
75
+ completion_message = result[0]['message']
76
+ thoughts = completion_message.get('reasoning', '')
77
+ text = completion_message.get('content', '')
78
+ else:
79
+ thoughts = ''
80
+ text = ''
81
+
82
+ return thoughts, text
83
+
84
+
85
+ if __name__ == "__main__":
86
+ ...
@@ -0,0 +1,82 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Python
3
+
4
+ """Copyright (c) Alexander Fedotov.
5
+ This source code is licensed under the license found in the
6
+ LICENSE file in the root directory of this source tree.
7
+ """
8
+ import urllib.request
9
+ import urllib.error
10
+ import json
11
+ from os import environ
12
+
13
+
14
+ def respond(messages, instructions, **kwargs):
15
+ """
16
+ """
17
+ api_key = environ.get("DEPSEK_API_KEY")
18
+ api_base = environ.get("DEPSEK_API_BASE", "https://api.deepseek.com")
19
+ default_model = environ.get("DEPSEK_DEFAULT_MODEL", "deepseek-flash")
20
+
21
+ instruction = kwargs.get('system_instruction', instructions)
22
+ first_message = [dict(role='system', content=instruction)] if instruction else []
23
+
24
+ # add contents and user text to the first (instruction) message
25
+ first_message.extend(messages)
26
+ instruction_and_contents = first_message
27
+
28
+ # Define the payload
29
+ payload = {
30
+ "model": kwargs.get("model", default_model),
31
+ "messages": instruction_and_contents,
32
+ "max_tokens": kwargs.get("max_tokens", 64000),
33
+ "temperature": kwargs.get("temperature", 1.0),
34
+ "reasoning_effort": kwargs.get("reasoning_effort", "max"),
35
+ "thinking": {
36
+ "type": "enabled"
37
+ }
38
+ }
39
+
40
+ # Convert data dictionary to JSON and encode it to bytes
41
+ data_bytes = json.dumps(payload).encode('utf-8')
42
+
43
+ # Set the mandatory headers
44
+ headers = {
45
+ "Content-Type": "application/json",
46
+ "Authorization": f"Bearer {api_key}",
47
+ "User-Agent": "Exploring-Machine"
48
+ }
49
+
50
+ # Create the Request object
51
+ req = urllib.request.Request(
52
+ f'{api_base}/chat/completions',
53
+ data=data_bytes,
54
+ headers=headers,
55
+ method="POST")
56
+
57
+ try:
58
+ # Execute the request
59
+ with urllib.request.urlopen(req, timeout=300) as response:
60
+ response_data = response.read().decode('utf-8')
61
+ output = json.loads(response_data)
62
+ message = output['choices'][0]['message']
63
+ text = message['content']
64
+ thoughts = message['reasoning_content']
65
+
66
+ return thoughts, text
67
+
68
+ except urllib.error.HTTPError as e:
69
+ # Handle HTTP errors (e.g., 401 Unauthorized, 400 Bad Request)
70
+ error_info = e.read().decode('utf-8', errors='ignore')
71
+ print(f"HTTP Error {e.code}: {e.reason}")
72
+ print(f"Error Details: {error_info}")
73
+ return '', ''
74
+
75
+ except urllib.error.URLError as e:
76
+ # Handle network/connection errors
77
+ print(f"Failed to reach the server: {e.reason}")
78
+ return '', ''
79
+
80
+
81
+ if __name__ == '__main__':
82
+ ...
@@ -0,0 +1,78 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Python
3
+
4
+ """Copyright (c) Alexander Fedotov.
5
+ This source code is licensed under the license found in the
6
+ LICENSE file in the root directory of this source tree.
7
+ """
8
+ import urllib.request
9
+ import urllib.error
10
+ import json
11
+ from os import environ
12
+
13
+
14
+ def respond(messages=None, instructions=None, **kwargs):
15
+ """ All parameters should be in kwargs, but they are optional
16
+ """
17
+ api_key = environ.get("ANTHROPIC_API_KEY")
18
+ api_base = environ.get("ANTHROPIC_API_BASE", "https://api.anthropic.com/v1")
19
+ api_type = environ.get("ANTHROPIC_VERSION", "2023-06-01")
20
+ default_model = environ.get("ANTHROPIC_DEFAULT_MODEL", 'claude-opus-4-6')
21
+
22
+ # Define the payload
23
+ payload = {
24
+ "model": kwargs.get("model", default_model),
25
+ "thinking": {"type": "adaptive"},
26
+ "system": kwargs.get("system_instruction", instructions),
27
+ "messages": messages,
28
+ "max_tokens": kwargs.get("max_tokens", 100000),
29
+ "stop_sequences": kwargs.get("stop_sequences", ['stop']),
30
+ "stream": kwargs.get("stream", False),
31
+ "temperature": 1.0,
32
+ "output_config": kwargs.get("output_config", {"effort": "low"}),
33
+ "metadata": kwargs.get("metadata", None)
34
+ }
35
+
36
+ # Convert data dictionary to JSON and encode it to bytes
37
+ data_bytes = json.dumps(payload).encode('utf-8')
38
+
39
+ headers = {
40
+ "x-api-key": api_key,
41
+ "anthropic-version": api_type,
42
+ "content-type": "application/json",
43
+ "User-Agent": "Exploring-Machine"
44
+ }
45
+
46
+ # Create the Request object
47
+ req = urllib.request.Request(
48
+ f'{api_base}/messages',
49
+ data=data_bytes,
50
+ headers=headers,
51
+ method="POST")
52
+
53
+ try:
54
+ # Execute the request
55
+ with urllib.request.urlopen(req, timeout=300) as response:
56
+ response_data = response.read().decode('utf-8')
57
+ output = json.loads(response_data)
58
+ text = ''
59
+ thoughts = ''
60
+ for chunk in output.get("content"):
61
+ if chunk['type'] == 'text':
62
+ addition = chunk['text']
63
+ if addition not in ('\n\n', '\n'):
64
+ text += addition
65
+
66
+ elif chunk['type'] == 'thinking':
67
+ thoughts += chunk['thinking']
68
+
69
+ return thoughts, text
70
+
71
+ except Exception as e:
72
+ print("Unable to generate Message response")
73
+ print(f"Exception: {e}")
74
+ return ['', '']
75
+
76
+
77
+ if __name__ == "__main__":
78
+ ...
@@ -0,0 +1,87 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Python
3
+
4
+ """Copyright (c) Alexander Fedotov.
5
+ This source code is licensed under the license found in the
6
+ LICENSE file in the root directory of this source tree.
7
+ """
8
+ import json
9
+ import urllib.request
10
+ import urllib.error
11
+ from os import environ
12
+
13
+
14
+ def decode_output(output):
15
+ # Parse the result
16
+ text = ''; thoughts = ''
17
+ for part in output:
18
+ part_type = part.get('type', None)
19
+ if part_type == 'message':
20
+ text = " ".join([chunk['text'] for chunk in part['content'] if chunk['type'] == 'output_text'])
21
+ elif part_type == 'reasoning':
22
+ thoughts = " ".join([chunk['text'] for chunk in part['summary'] if chunk['type'] == 'summary_text'])
23
+ function_calls = [part for part in output if part['type'] == 'function_call']
24
+ return thoughts, text, function_calls
25
+
26
+
27
+ def respond(messages=None, instructions=None, tools=None, **kwargs):
28
+ """ All parameters should be in kwargs, but they are optional
29
+ """
30
+ # The configuration.
31
+ api_key = environ.get('FIREWORKS_API_KEY')
32
+ api_base = environ.get('FIREWORKS_BASE_URL', 'https://api.fireworks.ai/inference/v1')
33
+ default_model = environ.get('FIREWORKS_MODEL', 'accounts/fireworks/models/kimi-k3')
34
+
35
+ headers = {
36
+ "Content-Type": "application/json",
37
+ "Authorization": "Bearer " + api_key,
38
+ "User-Agent": "Exploring-Machine"
39
+ }
40
+
41
+ # Receive the instruction
42
+ instruction = kwargs.get('system_instruction', instructions)
43
+
44
+ # Define the initial payload
45
+ payload = {
46
+ "model": kwargs.get("model", default_model),
47
+ "instructions": instruction,
48
+ "input": messages,
49
+ "max_output_tokens": kwargs.get("max_tokens", 132000),
50
+ "reasoning": {
51
+ "effort": "max",
52
+ "summary": "detailed"
53
+ }
54
+ }
55
+ # Convert data dictionary to JSON and encode it to bytes
56
+ data_bytes = json.dumps(payload).encode('utf-8')
57
+ # Create the Request object
58
+ req = urllib.request.Request(
59
+ f'{api_base}/responses',
60
+ data=data_bytes,
61
+ headers=headers,
62
+ method="POST")
63
+ # Try to query
64
+ try:
65
+ # Execute the request
66
+ with urllib.request.urlopen(req, timeout=3000) as response:
67
+ response_data = response.read().decode('utf-8')
68
+ output = json.loads(response_data)
69
+ thoughts, text, function_calls = decode_output(output.get('output', {}))
70
+
71
+ except urllib.error.HTTPError as e:
72
+ # Handle HTTP errors (e.g., 401 Unauthorized, 400 Bad Request)
73
+ error_info = e.read().decode('utf-8', errors='ignore')
74
+ print(f"HTTP Error {e.code}: {e.reason}")
75
+ print(f"Error Details: {error_info}")
76
+ return '', ''
77
+
78
+ except urllib.error.URLError as e:
79
+ # Handle network/connection errors
80
+ print(f"Failed to reach the server: {e.reason}")
81
+ return '', ''
82
+
83
+ return thoughts, text
84
+
85
+
86
+ if __name__ == "__main__":
87
+ ...
@@ -0,0 +1,164 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Python
3
+
4
+ """Copyright (c) Alexander Fedotov.
5
+ This source code is licensed under the license found in the
6
+ LICENSE file in the root directory of this source tree.
7
+ """
8
+ import urllib.request
9
+ import urllib.error
10
+ import json
11
+ from os import environ
12
+
13
+ api_key = environ.get("METAI_API_KEY", '')
14
+ default_model = environ.get("METAI_DEFAULT_MODEL", 'muse-spark-1.1')
15
+ api_base = environ.get("METAI_API_BASE", "https://api.meta.ai/v1")
16
+
17
+
18
+ # Set the mandatory headers
19
+ headers = {
20
+ "Content-Type": "application/json",
21
+ "Authorization": f"Bearer {api_key}",
22
+ "User-Agent": "Exploring-Machine"
23
+ }
24
+
25
+
26
+ def get_weather(location):
27
+ # print(f"Executing weather tool for location: {location}")
28
+ return {"temperature": "72F", "condition": "Sunny"}
29
+
30
+
31
+ def query(payload):
32
+ # Convert data dictionary to JSON and encode it to bytes
33
+ data_bytes = json.dumps(payload).encode('utf-8')
34
+ # Create the Request object
35
+ req = urllib.request.Request(
36
+ f'{api_base}/responses',
37
+ data=data_bytes,
38
+ headers=headers,
39
+ method="POST")
40
+ # Try to query
41
+ try:
42
+ # Execute the request
43
+ with urllib.request.urlopen(req, timeout=3000) as response:
44
+ response_data = response.read().decode('utf-8')
45
+ output = json.loads(response_data)
46
+ return output
47
+
48
+ except urllib.error.HTTPError as e:
49
+ # Handle HTTP errors (e.g., 401 Unauthorized, 400 Bad Request)
50
+ error_info = e.read().decode('utf-8', errors='ignore')
51
+ print(f"HTTP Error {e.code}: {e.reason}")
52
+ print(f"Error Details: {error_info}")
53
+ return {}
54
+
55
+ except urllib.error.URLError as e:
56
+ # Handle network/connection errors
57
+ print(f"Failed to reach the server: {e.reason}")
58
+ return {}
59
+
60
+
61
+ def decode_output(output):
62
+ # Parse the result
63
+ text = ''; thoughts = ''
64
+ for part in output:
65
+ part_type = part.get('type', None)
66
+ if part_type == 'message':
67
+ text = " ".join([chunk['text'] for chunk in part['content'] if chunk['type'] == 'output_text'])
68
+ elif part_type == 'reasoning':
69
+ thoughts = " ".join([chunk['text'] for chunk in part['summary'] if chunk['type'] == 'summary_text'])
70
+ function_calls = [part for part in output if part['type'] == 'function_call']
71
+ return thoughts, text, function_calls
72
+
73
+
74
+ def respond(messages=None, instructions=None, tools=None, **kwargs):
75
+ """ All parameters should be in kwargs, but they are optional
76
+ """
77
+ # Receive the instruction
78
+ instruction = kwargs.get('system_instruction', instructions)
79
+
80
+ # Define the initial payload
81
+ payload = {
82
+ "model": kwargs.get("model", default_model),
83
+ "instructions": instruction,
84
+ "input": messages,
85
+ "max_output_tokens": kwargs.get("max_tokens", 132000),
86
+ "prompt_cache_retention": "in_memory",
87
+ "include": ["reasoning.encrypted_content"],
88
+ "reasoning": {
89
+ "effort": "high",
90
+ "summary": "detailed"
91
+ }
92
+ }
93
+ # Tools if there are some
94
+ if tools:
95
+ payload['tools'] = tools
96
+ payload['tool_choice'] = 'auto'
97
+
98
+ while True:
99
+ # Query the API
100
+ result = query(payload)
101
+ # id of the response
102
+ response_id = result['id']
103
+ thoughts, text, function_calls = decode_output(result.get('output', {}))
104
+
105
+ if function_calls:
106
+ function_outputs_messages = []
107
+ for function_call in function_calls:
108
+ call_id = function_call.get('call_id')
109
+ func_name = function_call.get('name')
110
+ func_args_str = function_call.get('arguments', '{}')
111
+ try:
112
+ if isinstance(func_args_str, str):
113
+ func_args = json.loads(func_args_str)
114
+ else:
115
+ func_args = func_args_str
116
+ except Exception as e:
117
+ func_args = {}
118
+ print(f"Error parsing tool arguments for {func_name}: {e}")
119
+
120
+ # Look up tool by name in globals and caller frames
121
+ func = globals().get(func_name)
122
+ if not func:
123
+ import inspect
124
+ frame = inspect.currentframe().f_back
125
+ while frame:
126
+ if func_name in frame.f_globals:
127
+ func = frame.f_globals[func_name]
128
+ break
129
+ frame = frame.f_back
130
+
131
+ if func and callable(func):
132
+ try:
133
+ tool_result = func(**func_args)
134
+ if isinstance(tool_result, (dict, list)):
135
+ result = json.dumps(tool_result)
136
+ else:
137
+ result = str(tool_result)
138
+ except Exception as e:
139
+ result = f"Error executing tool {func_name}: {str(e)}"
140
+ print(result)
141
+ else:
142
+ result = f"Error: Tool function {func_name} not found."
143
+ print(result)
144
+
145
+ tool_message = {
146
+ "type": "function_call_output",
147
+ "call_id": call_id,
148
+ "output": result
149
+ }
150
+ function_outputs_messages.append(tool_message)
151
+
152
+ # Now that all responses have been gathered
153
+ # we can change the payload and send them back
154
+ payload['include'] = [] # must be removed if response_id
155
+ payload['previous_response_id'] = response_id
156
+ payload['input'] = function_outputs_messages
157
+ else:
158
+ break
159
+
160
+ return thoughts, text
161
+
162
+
163
+ if __name__ == "__main__":
164
+ ...