oskaragent 0.1.37__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.
- oskaragent-0.1.37/LICENSE +19 -0
- oskaragent-0.1.37/PKG-INFO +628 -0
- oskaragent-0.1.37/README.md +593 -0
- oskaragent-0.1.37/pyproject.toml +49 -0
- oskaragent-0.1.37/setup.cfg +4 -0
- oskaragent-0.1.37/src/oskaragent/__init__.py +49 -0
- oskaragent-0.1.37/src/oskaragent/agent.py +1608 -0
- oskaragent-0.1.37/src/oskaragent/agent_config.py +328 -0
- oskaragent-0.1.37/src/oskaragent/agent_mcp_tools.py +102 -0
- oskaragent-0.1.37/src/oskaragent/agent_tools.py +939 -0
- oskaragent-0.1.37/src/oskaragent/converters/__init__.py +25 -0
- oskaragent-0.1.37/src/oskaragent/converters/csv_md.py +20 -0
- oskaragent-0.1.37/src/oskaragent/converters/docx_md.py +167 -0
- oskaragent-0.1.37/src/oskaragent/converters/helpers.py +67 -0
- oskaragent-0.1.37/src/oskaragent/converters/html_md.py +357 -0
- oskaragent-0.1.37/src/oskaragent/converters/json_csv.py +30 -0
- oskaragent-0.1.37/src/oskaragent/converters/json_md.py +119 -0
- oskaragent-0.1.37/src/oskaragent/converters/pdf_md.py +230 -0
- oskaragent-0.1.37/src/oskaragent/converters/pptx_md.py +161 -0
- oskaragent-0.1.37/src/oskaragent/helpers.py +171 -0
- oskaragent-0.1.37/src/oskaragent/rag/__init__.py +10 -0
- oskaragent-0.1.37/src/oskaragent/rag/faiss_kb.py +448 -0
- oskaragent-0.1.37/src/oskaragent/rag/file_renderers.py +0 -0
- oskaragent-0.1.37/src/oskaragent/rag/knowledgebase.py +117 -0
- oskaragent-0.1.37/src/oskaragent/rag/sql_repository.py +89 -0
- oskaragent-0.1.37/src/oskaragent.egg-info/PKG-INFO +628 -0
- oskaragent-0.1.37/src/oskaragent.egg-info/SOURCES.txt +28 -0
- oskaragent-0.1.37/src/oskaragent.egg-info/dependency_links.txt +1 -0
- oskaragent-0.1.37/src/oskaragent.egg-info/requires.txt +20 -0
- oskaragent-0.1.37/src/oskaragent.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Copyright (c) 2025 The Python Packaging Authority
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
in the Software without restriction, including without limitation the rights
|
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
furnished to do so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
|
11
|
+
copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
19
|
+
SOFTWARE.
|
|
@@ -0,0 +1,628 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: oskaragent
|
|
3
|
+
Version: 0.1.37
|
|
4
|
+
Summary: Oskar - package to create and confiuguration of conversasional agents based on OpenAI protocolo.
|
|
5
|
+
Author-email: jcordeiro69 <jcordeiromartins69@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Source, https://github.com/jcordeiro69/oskaragent
|
|
8
|
+
Project-URL: Homepage, https://github.com/jcordeiro69/oskaragent
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.12
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: openai
|
|
15
|
+
Requires-Dist: mcp
|
|
16
|
+
Requires-Dist: faiss-cpu
|
|
17
|
+
Requires-Dist: numpy
|
|
18
|
+
Requires-Dist: pandas
|
|
19
|
+
Requires-Dist: pyyaml
|
|
20
|
+
Requires-Dist: pypdf
|
|
21
|
+
Requires-Dist: pdfkit
|
|
22
|
+
Requires-Dist: pdfminer.six
|
|
23
|
+
Requires-Dist: python-docx
|
|
24
|
+
Requires-Dist: python-pptx
|
|
25
|
+
Requires-Dist: pillow
|
|
26
|
+
Requires-Dist: lxml
|
|
27
|
+
Requires-Dist: markdown2
|
|
28
|
+
Requires-Dist: beautifulsoup4
|
|
29
|
+
Requires-Dist: matplotlib
|
|
30
|
+
Requires-Dist: seaborn
|
|
31
|
+
Requires-Dist: tabulate
|
|
32
|
+
Requires-Dist: colorama
|
|
33
|
+
Requires-Dist: pyodbc
|
|
34
|
+
Dynamic: license-file
|
|
35
|
+
|
|
36
|
+
# Oskar Agent
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Overview
|
|
41
|
+
|
|
42
|
+
Oskar is a multipurpose conversational agent. It integrates with the OpenAI Responses API (using `gpt-5` models by default) and activates a dynamic set of tools (Python execution, file read/write, searches, RAG via Faiss, subordinate agents, corporate integrations, etc.). Configuration is done via `AgentConfig` (`Oskar/agent_config.py`), which is responsible for prompts, tools, knowledge bases, and analytical sources.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Prerequisites
|
|
47
|
+
|
|
48
|
+
- Python 3.12 or higher.
|
|
49
|
+
|
|
50
|
+
- Dependencies listed in `requirements.txt`.
|
|
51
|
+
|
|
52
|
+
- Environment variables `OPENAI_API_KEY` (required for online use) and optional `OPENAI_BASE_URL`.
|
|
53
|
+
|
|
54
|
+
- To enable SerpAPI (`search_web_tool`), set `SERPAPI_API_KEY`.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Essential Concepts of the `Oskar` Class
|
|
59
|
+
|
|
60
|
+
- `AgentConfig`: dataclass with slots defining model, prompt, tools, knowledge sources (`knowledge_base`), files (`working_files`), and databases (`working_databases`).
|
|
61
|
+
|
|
62
|
+
- `Oskar.answer(question, **kwargs)`: generates a `message_id`, prepares the interpolated prompt, builds messages with history/attachments via `attached_files`, sets `reasoning_effort`, orchestrates the call to the Responses API (with a tool loop and offline fallback), and aggregates generated artifacts before returning the complete payload (text, metadata, files, and usage).
|
|
63
|
+
|
|
64
|
+
- `response_callback`: optional function called after each response with the complete payload.
|
|
65
|
+
|
|
66
|
+
- `attached_files`: parameter that accepts a file path (string or list) to attach content to the question.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Detailed Class Reference
|
|
71
|
+
|
|
72
|
+
### `AgentConfig`
|
|
73
|
+
|
|
74
|
+
**Properties**
|
|
75
|
+
|
|
76
|
+
- `agent_id`: unique identifier of the agent; defaults to `agent_name` when not provided.
|
|
77
|
+
|
|
78
|
+
- `agent_name`: displayed name of the agent, used in prompts and history (default: `"Oskar"`).
|
|
79
|
+
|
|
80
|
+
- `model`: primary model used by the agent (default: `"gpt-5"`).
|
|
81
|
+
|
|
82
|
+
- `model_settings`: optional dictionary with extra parameters (e.g., `history_window_size`, temperature).
|
|
83
|
+
|
|
84
|
+
- `system_prompt`: custom system instructions; when absent, a default message is generated containing the agent’s name.
|
|
85
|
+
|
|
86
|
+
- `description`: short text describing the agent for listings or auxiliary prompts.
|
|
87
|
+
|
|
88
|
+
- `tools_names`: list of allowed tools beyond the defaults (calculator, date/time).
|
|
89
|
+
|
|
90
|
+
- `custom_tools`: dictionary with dynamically registered external tools.
|
|
91
|
+
|
|
92
|
+
- `knowledge_base`: list of Chroma sources (`name`, `folder`, `collection`) used to build RAG retrievers.
|
|
93
|
+
|
|
94
|
+
- `working_files`: metadata for CSV/auxiliary files available during the session (name, description, path).
|
|
95
|
+
|
|
96
|
+
- `working_databases`: definitions of SQL databases that automatically generate CSVs (`name`, `description`, `connection_string`, `query`).
|
|
97
|
+
|
|
98
|
+
- `json_config`: `InitVar` used only by the constructor to hydrate the instance from a dictionary.
|
|
99
|
+
|
|
100
|
+
**Methods**
|
|
101
|
+
|
|
102
|
+
- `to_json()`: serializes all public fields into a dictionary ready for persistence.
|
|
103
|
+
|
|
104
|
+
- `restore_from_json(agent_config)`: updates only the attributes present in the provided dictionary.
|
|
105
|
+
|
|
106
|
+
### `Oskar`
|
|
107
|
+
|
|
108
|
+
**Exposed properties and attributes**
|
|
109
|
+
|
|
110
|
+
- `agent_config`: active `AgentConfig` instance for the session.
|
|
111
|
+
|
|
112
|
+
- `input_data`: dictionary with variables to be interpolated into prompts.
|
|
113
|
+
|
|
114
|
+
- `session_id`: UUID of the current session (auto-generated if omitted).
|
|
115
|
+
|
|
116
|
+
- `session_name`: optional label used in persistence and reporting.
|
|
117
|
+
|
|
118
|
+
- `session_created_at` / `session_updated_at`: ISO timestamps for creation and last update.
|
|
119
|
+
|
|
120
|
+
- `working_folder`: base directory for generated files and artifacts.
|
|
121
|
+
|
|
122
|
+
- `is_verbose`: enables detailed logs when `True`.
|
|
123
|
+
|
|
124
|
+
- `tools`: dictionary with currently enabled tools (default, optional, and corporate).
|
|
125
|
+
|
|
126
|
+
- `message_history`: structured list of questions, answers, attachments, and token usage.
|
|
127
|
+
|
|
128
|
+
- `history_window_size`: number of user/agent message pairs kept in short context (default: `5`).
|
|
129
|
+
|
|
130
|
+
- `retrievers`: RAG collections loaded from the `knowledge_base`.
|
|
131
|
+
|
|
132
|
+
- `response_callback`: optional function called after each consolidated response.
|
|
133
|
+
|
|
134
|
+
- `id`: read-only alias for the agent.
|
|
135
|
+
|
|
136
|
+
- `name`: agent's displayed name.
|
|
137
|
+
|
|
138
|
+
- `description`: agent description, purpose, and capabilities.
|
|
139
|
+
|
|
140
|
+
- `model`: returns the model name.
|
|
141
|
+
|
|
142
|
+
- `reasoning_effort`: sets the agent’s reasoning mode ("none" | "low" | "medium" | "high"), defaulting to "none".
|
|
143
|
+
|
|
144
|
+
**Public Methods**
|
|
145
|
+
|
|
146
|
+
- `__init__(..., exec_custom_tool_fn=None)`: instantiates the agent with active configuration and session, prepares factories for tools (default, corporate, and custom), defines callbacks and working directories, and calls `_setup_agent()` to build the OpenAI client, registries, and RAG retrievers.
|
|
147
|
+
|
|
148
|
+
| Parameter | Description | Default |
|
|
149
|
+
| ------------------------------ | ---------------------------------------------------------- | ---------------- |
|
|
150
|
+
| `agent_config` | Agent configuration (model, prompt, tools, RAG sources). | `AgentConfig()` |
|
|
151
|
+
| `input_data` | Auxiliary variables interpolated in prompts. | `{}` |
|
|
152
|
+
| `session_id` | Session UUID; auto-generated if absent. | `uuid4()` |
|
|
153
|
+
| `session_name` | Friendly session name. | `None` |
|
|
154
|
+
| `session_created_at` | Timestamp of session creation. | `datetime.now()` |
|
|
155
|
+
| `session_updated_at` | Timestamp of last update. | `datetime.now()` |
|
|
156
|
+
| `working_folder` | Base directory for `output/<session_id>`. | `Path.cwd()` |
|
|
157
|
+
| `is_verbose` | Enables detailed agent logs. | `False` |
|
|
158
|
+
| `response_callback` | Optional function called after each consolidated response. | `None` |
|
|
159
|
+
| `get_builtin_custom_tools_fn` | Alternative factory for loading corporate tools. | `None` |
|
|
160
|
+
| `build_custom_tool_schemas_fn` | Additional builder for custom tool schemas. | `None` |
|
|
161
|
+
| `exec_custom_tool_fn` | Custom executor for custom tools. | `None` |
|
|
162
|
+
|
|
163
|
+
- `to_json()`: exports `agent_config`, session metadata, derived state (tools, flags), and `message_history` into a dictionary ready for persistence or transport.
|
|
164
|
+
|
|
165
|
+
- `from_json(data, working_folder)`: class method that reconstructs configuration, session chronology, and history from the snapshot returned by `to_json()`, respecting the provided `working_folder` to rehydrate attachments and outputs.
|
|
166
|
+
|
|
167
|
+
- `add_subordinated_agent(subordinate_agent, role=None)`: associates another Oskar instance as a subordinate collaborator, allowing only one agent per name, replicating working directory and verbosity, and optionally updating the description with the given role.
|
|
168
|
+
|
|
169
|
+
- `get_pretty_messages_history(message_format='raw', list_subordinated_agents_history=False)`: formats history into blocks ready for visualization (`raw` or HTML), grouping question/answer pairs and optionally including subordinate agent interactions.
|
|
170
|
+
|
|
171
|
+
- `answer(question, message_format='raw', attached_files=None, model=None, reasoning_effort=None, action='chat', include_history=True, is_consult_prompt=False)`: prepares the prompt with session variables, ensures output folders exist, attaches files, sets reasoning effort, records input in history, builds tool schemas, and performs up to three iterations with the Responses API (or offline mode), returning content, metadata, attachments, and token usage.
|
|
172
|
+
|
|
173
|
+
- `delete_old_files(max_age_days=30)`: removes old files sent to the OpenAI API, returning a list of tuples (`id`, filename, creation date) for each removed item.
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Converters (`Oskar.converters`)
|
|
178
|
+
|
|
179
|
+
- `convert_csv_to_markdown_table(csv_data: str)`: converts raw CSV content (with header) into a Markdown table without an index column.
|
|
180
|
+
|
|
181
|
+
- `convert_dict_to_markdown(data: dict, md_path: str)`: serializes a dictionary into Markdown and writes it to the given path.
|
|
182
|
+
|
|
183
|
+
- `convert_docx_to_markdown(docx_path: str, md_path: str, media_dir: str | None = None)`: converts a DOCX into Markdown, exporting media to the specified folder.
|
|
184
|
+
|
|
185
|
+
- `convert_json_to_markdown(json_data: dict | list, doc_title: str = "Documento")`: serializes dictionaries or lists into structured Markdown text.
|
|
186
|
+
|
|
187
|
+
- `convert_json_to_csv(recs_json: list, filename: str)`: saves a list of dictionaries into a CSV file, sanitizing line breaks and truncating long strings.
|
|
188
|
+
|
|
189
|
+
- `convert_markdown_to_html(md_path: str, img_dir: str | None = None, insert_header: bool = True)`: generates HTML from Markdown, optionally adjusting image paths and inserting a default header.
|
|
190
|
+
|
|
191
|
+
- `convert_markdown_to_html_block(text: str, flag_insert_copy_to_clipboard_command: bool = True)`: converts Markdown text into HTML and also returns a list of detected code-block languages.
|
|
192
|
+
|
|
193
|
+
- `convert_markdown_to_pdf(md_filename: str, img_dir: str)`: renders Markdown as a PDF via `wkhtmltopdf`, reusing the generated intermediate HTML.
|
|
194
|
+
|
|
195
|
+
- `convert_pdf_to_markdown(pdf_path: str, md_path: str | None = None)`: extracts text from a PDF, attempts to identify headings, and returns the resulting Markdown file path.
|
|
196
|
+
|
|
197
|
+
- `convert_pptx_to_markdown(pptx_path: str, md_path: str, media_dir: str | None = None)`: converts PPTX slides to Markdown, extracting text, tables, images, and charts.
|
|
198
|
+
|
|
199
|
+
- `decode_file_from_str(encoded_data: str, out_path: str)`: decodes `b64:` or `b64+zlib:` strings into a binary file.
|
|
200
|
+
|
|
201
|
+
- `encode_file(pathname: str, compress: bool = True)`: reads a binary file and returns a JSON-safe encoded string, optionally compressing with zlib.
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## Use Case Examples (`tests/`)
|
|
206
|
+
|
|
207
|
+
The scripts in `tests/` function as complete recipes. All can be executed directly (`python tests/<script>.py`) after configuring dependencies.
|
|
208
|
+
|
|
209
|
+
### 1. Basic Usage and Persistence
|
|
210
|
+
|
|
211
|
+
- `tests/1a_test_basico.py`: instantiates the agent, registers a usage callback, and sends a simple question.
|
|
212
|
+
|
|
213
|
+
```python
|
|
214
|
+
import json
|
|
215
|
+
from oskaragent.agent import Oskar
|
|
216
|
+
from oskaragent.agent_config import AgentConfig
|
|
217
|
+
|
|
218
|
+
ag_cfg = AgentConfig(model_settings={"history_window_size": 5})
|
|
219
|
+
agent = Oskar(agent_config=ag_cfg, is_verbose=True)
|
|
220
|
+
res = agent.answer("Who is the president of Brazil?")
|
|
221
|
+
print(json.dumps(res, indent=2, ensure_ascii=False))
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
- `tests/1b_test_history.py`: demonstrates `to_json()` and `Oskar.from_json(...)` to persist the full session history and restore it before the next question.
|
|
225
|
+
|
|
226
|
+
```python
|
|
227
|
+
import json
|
|
228
|
+
from oskaragent.agent import Oskar
|
|
229
|
+
from oskaragent.agent_config import AgentConfig
|
|
230
|
+
|
|
231
|
+
ag_cfg = AgentConfig(
|
|
232
|
+
model_settings={"history_window_size": 5},
|
|
233
|
+
system_prompt="You are a helpful assistant named oskaragent.",
|
|
234
|
+
)
|
|
235
|
+
agent = Oskar(agent_config=ag_cfg, is_verbose=True)
|
|
236
|
+
r1 = agent.answer("My favorite color is blue. What is your favorite color?")
|
|
237
|
+
snapshot = agent.to_json()
|
|
238
|
+
agent2 = Oskar.from_json(snapshot)
|
|
239
|
+
r2 = agent2.answer("What is my favorite color?")
|
|
240
|
+
print(json.dumps(r2, indent=2, ensure_ascii=False))
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### 2. Internal Tools
|
|
244
|
+
|
|
245
|
+
- `tests/2a_test_tool_python.py`: enables `execute_python_code_tool` so the model can generate and run pandas/matplotlib scripts.
|
|
246
|
+
|
|
247
|
+
```python
|
|
248
|
+
import json
|
|
249
|
+
from oskaragent.agent import Oskar
|
|
250
|
+
from oskaragent.agent_config import AgentConfig
|
|
251
|
+
|
|
252
|
+
ag_cfg = AgentConfig(
|
|
253
|
+
tools_names=["execute_python_code_tool"],
|
|
254
|
+
system_prompt="Use execute_python_code_tool to run Python code.",
|
|
255
|
+
)
|
|
256
|
+
agent = Oskar(agent_config=ag_cfg, is_verbose=True)
|
|
257
|
+
res = agent.answer(
|
|
258
|
+
"Create and run a bar chart with matplotlib using the execute_python_code_tool."
|
|
259
|
+
)
|
|
260
|
+
print(json.dumps(res, indent=2, ensure_ascii=False))
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
- `tests/2b_test_tool_calculator.py`: reinforces usage of `calculator_tool`, explicitly invoking it via `action='tool:calculator_tool'`.
|
|
264
|
+
|
|
265
|
+
```python
|
|
266
|
+
import json
|
|
267
|
+
from oskaragent.agent import Oskar
|
|
268
|
+
from oskaragent.agent_config import AgentConfig
|
|
269
|
+
|
|
270
|
+
ag_cfg = AgentConfig(
|
|
271
|
+
tools_names=["calculator_tool"],
|
|
272
|
+
system_prompt=(
|
|
273
|
+
"You are an assistant focused on calculations. Whenever there is a mathematical expression, "
|
|
274
|
+
"use the 'calculator_tool'."
|
|
275
|
+
),
|
|
276
|
+
)
|
|
277
|
+
agent = Oskar(agent_config=ag_cfg, is_verbose=True)
|
|
278
|
+
expression = "1024 + 12 + 1"
|
|
279
|
+
question = f"Calculate the expression below using calculator_tool: {expression}"
|
|
280
|
+
res = agent.answer(question, action="tool:calculator_tool")
|
|
281
|
+
print(json.dumps(res, indent=2, ensure_ascii=False))
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
- `tests/2c_test_savefile_tool.py`: adds `write_file_tool` to save artifacts to disk (e.g., a PlantUML diagram). The agent is instructed to use the tool whenever requested.
|
|
285
|
+
|
|
286
|
+
```python
|
|
287
|
+
import json
|
|
288
|
+
from oskaragent.agent import Oskar
|
|
289
|
+
from oskaragent.agent_config import AgentConfig
|
|
290
|
+
|
|
291
|
+
ag_cfg = AgentConfig(
|
|
292
|
+
tools_names=["write_file_tool"],
|
|
293
|
+
system_prompt=(
|
|
294
|
+
"You are an agent named oskaragent. When asked to save content, "
|
|
295
|
+
"use the 'write_file_tool'."
|
|
296
|
+
),
|
|
297
|
+
model_settings={"history_window_size": 5},
|
|
298
|
+
)
|
|
299
|
+
agent = Oskar(agent_config=ag_cfg, is_verbose=True)
|
|
300
|
+
agent.answer("Generate a PlantUML diagram of a regular expression for international phone numbers.")
|
|
301
|
+
res = agent.answer("Save the PlantUML diagram to a file.")
|
|
302
|
+
print(json.dumps(res, indent=2, ensure_ascii=False))
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### 3. File Upload and Manipulation
|
|
306
|
+
|
|
307
|
+
- `tests/3a_test_upload_md.py`: sends a Markdown file (`tests/sources/cristianismo.md`) so the agent can produce an objective summary. Uses `attached_files` with the absolute file path.
|
|
308
|
+
|
|
309
|
+
```python
|
|
310
|
+
from pathlib import Path
|
|
311
|
+
from oskaragent.agent import Oskar
|
|
312
|
+
from oskaragent.agent_config import AgentConfig
|
|
313
|
+
|
|
314
|
+
md_path = Path("sources/cristianismo.md").resolve()
|
|
315
|
+
agent = Oskar(agent_config=AgentConfig(), is_verbose=True)
|
|
316
|
+
result = agent.answer(
|
|
317
|
+
question="Read the attached file and produce an objective summary in Portuguese.",
|
|
318
|
+
attached_files=str(md_path),
|
|
319
|
+
)
|
|
320
|
+
print(result.get("content", ""))
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
- `tests/3b_test_upload_img.py`: attaches an image (`tests/sources/img_pent.png`) and requests a detailed description.
|
|
324
|
+
|
|
325
|
+
```python
|
|
326
|
+
from pathlib import Path
|
|
327
|
+
from oskaragent.agent import Oskar
|
|
328
|
+
from oskaragent.agent_config import AgentConfig
|
|
329
|
+
|
|
330
|
+
img_path = (Path(__file__).parent / "sources" / "img_pent.png").resolve()
|
|
331
|
+
agent = Oskar(agent_config=AgentConfig(), is_verbose=False)
|
|
332
|
+
result = agent.answer(
|
|
333
|
+
question="Describe the attached image in detail in Portuguese.",
|
|
334
|
+
attached_files=str(img_path),
|
|
335
|
+
)
|
|
336
|
+
print(result.get("content", ""))
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
- `tests/3c_test_upload_pdf_compare.py`: sends two PDFs simultaneously and asks for a comparative analysis. Demonstrates that `attached_files` accepts a list.
|
|
340
|
+
|
|
341
|
+
```python
|
|
342
|
+
from pathlib import Path
|
|
343
|
+
from oskaragent.agent import Oskar
|
|
344
|
+
from oskaragent.agent_config import AgentConfig
|
|
345
|
+
|
|
346
|
+
pdf1_path = Path("sources/GlobalThreatReport2024.pdf").resolve()
|
|
347
|
+
pdf2_path = Path("sources/comptia-state-of-cybersecurity-2025.pdf").resolve()
|
|
348
|
+
agent = Oskar(agent_config=AgentConfig(), is_verbose=True)
|
|
349
|
+
result = agent.answer(
|
|
350
|
+
question="Create a comparative analysis of these two PDF documents in Portuguese.",
|
|
351
|
+
attached_files=[str(pdf1_path), str(pdf2_path)],
|
|
352
|
+
)
|
|
353
|
+
print(result.get("content", ""))
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### 4. Knowledge Retrieval (RAG)
|
|
357
|
+
|
|
358
|
+
- `tests/4_test_RAG.py`: activates a local Chroma source (`./tests/sources/vectorstore`) and explicitly calls `retriever_tool`.
|
|
359
|
+
|
|
360
|
+
```python
|
|
361
|
+
from oskaragent.agent import Oskar
|
|
362
|
+
from oskaragent.agent_config import AgentConfig
|
|
363
|
+
|
|
364
|
+
ag_cfg = AgentConfig(
|
|
365
|
+
knowledge_base=[{"name": "psychology", "folder": "./sources/vectorstore", "collection": "local-rag"}],
|
|
366
|
+
)
|
|
367
|
+
agent = Oskar(agent_config=ag_cfg, is_verbose=True)
|
|
368
|
+
agent.answer("How many sessions were conducted?", action="tool:retriever_tool")
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
### 5. Multi-Agent System (MAS)
|
|
372
|
+
|
|
373
|
+
- `tests/5_test_MAS.py`: creates an orchestrator agent and adds a subordinate with specific knowledge using `add_subordinate_agent`, enabling the `ask_to_agent_tool`.
|
|
374
|
+
|
|
375
|
+
```python
|
|
376
|
+
import json
|
|
377
|
+
from oskaragent.agent import Oskar
|
|
378
|
+
from oskaragent.agent_config import AgentConfig
|
|
379
|
+
|
|
380
|
+
assist_cfg = AgentConfig(
|
|
381
|
+
agent_id="AssistenteOskar",
|
|
382
|
+
agent_name="Assistant of oskaragent",
|
|
383
|
+
system_prompt="You know all employees of the company.",
|
|
384
|
+
)
|
|
385
|
+
agent_assistente = Oskar(agent_config=assist_cfg, is_verbose=True)
|
|
386
|
+
|
|
387
|
+
chefe_cfg = AgentConfig(agent_name="Boss", model_settings={"history_window_size": 5})
|
|
388
|
+
agent_chefe = Oskar(agent_config=chefe_cfg, is_verbose=True)
|
|
389
|
+
|
|
390
|
+
agent_chefe.add_subordinate_agent(
|
|
391
|
+
agent_assistente,
|
|
392
|
+
"Knows all company employees and their respective roles.",
|
|
393
|
+
)
|
|
394
|
+
res = agent_chefe.answer("What is Jacques’ job role?")
|
|
395
|
+
print(json.dumps(res, indent=2, ensure_ascii=False))
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
### 6. Corporate Integrations (`Oskar_cg_tools`)
|
|
399
|
+
|
|
400
|
+
- `tests/6a_test_cg_tool_Salesforce_OPO.py`: configures a sales persona and enables `get_salesforce_opportunity_info_tool` to query Salesforce opportunities.
|
|
401
|
+
|
|
402
|
+
```python
|
|
403
|
+
import json
|
|
404
|
+
from oskaragent.agent import Oskar
|
|
405
|
+
from oskaragent.agent_config import AgentConfig
|
|
406
|
+
from my_company_tools.agent_cg_tools import (
|
|
407
|
+
build_cg_tool_schemas,
|
|
408
|
+
exec_cg_tool,
|
|
409
|
+
get_builtin_cg_tools,
|
|
410
|
+
)
|
|
411
|
+
|
|
412
|
+
system_prompt = "Act as an analyst specialized in the Salesforce Sales module."
|
|
413
|
+
ag_cfg = AgentConfig(
|
|
414
|
+
system_prompt=system_prompt,
|
|
415
|
+
tools_names=["get_salesforce_opportunity_info_tool"],
|
|
416
|
+
model_settings={"history_window_size": 5},
|
|
417
|
+
)
|
|
418
|
+
agent = Oskar(
|
|
419
|
+
agent_config=ag_cfg,
|
|
420
|
+
get_builtin_custom_tools_fn=get_builtin_cg_tools,
|
|
421
|
+
build_custom_tool_schemas_fn=build_cg_tool_schemas,
|
|
422
|
+
exec_custom_tool_fn=exec_cg_tool,
|
|
423
|
+
is_verbose=True,
|
|
424
|
+
)
|
|
425
|
+
res = agent.answer("Show the timeline for opportunity OPO-ORIZON-2024-08-0001")
|
|
426
|
+
print(json.dumps(res, indent=2, ensure_ascii=False))
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
- `tests/6b_test_cg_tool_Salesforce_ITSM.py`: enables `get_salesforce_case_info_tool` for IT support analysis and instructs the agent to answer in Markdown.
|
|
430
|
+
|
|
431
|
+
```python
|
|
432
|
+
import json
|
|
433
|
+
from oskaragent.agent import Oskar
|
|
434
|
+
from oskaragent.agent_config import AgentConfig
|
|
435
|
+
from my_company_tools.agent_cg_tools import (
|
|
436
|
+
build_cg_tool_schemas,
|
|
437
|
+
exec_cg_tool,
|
|
438
|
+
get_builtin_cg_tools,
|
|
439
|
+
)
|
|
440
|
+
|
|
441
|
+
system_prompt = "Act as an analyst responsible for support tickets in Salesforce Service Cloud."
|
|
442
|
+
ag_cfg = AgentConfig(
|
|
443
|
+
system_prompt=system_prompt,
|
|
444
|
+
tools_names=["get_salesforce_case_info_tool"],
|
|
445
|
+
model_settings={"history_window_size": 5},
|
|
446
|
+
)
|
|
447
|
+
agent = Oskar(
|
|
448
|
+
agent_config=ag_cfg,
|
|
449
|
+
get_builtin_custom_tools_fn=get_builtin_cg_tools,
|
|
450
|
+
build_custom_tool_schemas_fn=build_cg_tool_schemas,
|
|
451
|
+
exec_custom_tool_fn=exec_cg_tool,
|
|
452
|
+
is_verbose=True,
|
|
453
|
+
)
|
|
454
|
+
res = agent.answer("Show the timeline for case 00042386")
|
|
455
|
+
print(json.dumps(res, indent=2, ensure_ascii=False))
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
- `tests/6c_test_custom_tool_SQL.py`: registers a custom SQL tool (`query_pessoas_tool`) via `AgentConfig.custom_tools`, illustrating parametric filters.
|
|
459
|
+
|
|
460
|
+
```python
|
|
461
|
+
import json
|
|
462
|
+
from oskaragent.agent import Oskar
|
|
463
|
+
from oskaragent.agent_config import AgentConfig
|
|
464
|
+
from my_company_tools.agent_cg_tools import (
|
|
465
|
+
build_cg_tool_schemas,
|
|
466
|
+
exec_cg_tool,
|
|
467
|
+
get_builtin_cg_tools,
|
|
468
|
+
)
|
|
469
|
+
|
|
470
|
+
custom_tools_info = {
|
|
471
|
+
"query_pessoas_tool": {
|
|
472
|
+
"func_name": "search_database_tool",
|
|
473
|
+
"description": "Search person data by name.",
|
|
474
|
+
"connection_string": "...",
|
|
475
|
+
"title": "People",
|
|
476
|
+
"queries": [
|
|
477
|
+
{
|
|
478
|
+
"title": "People found (first 30)",
|
|
479
|
+
"query": "select top 10 CO.Nome, CO.Email ... where ...",
|
|
480
|
+
}
|
|
481
|
+
],
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
ag_cfg = AgentConfig(custom_tools=custom_tools_info, model_settings={"history_window_size": 5})
|
|
485
|
+
agent = Oskar(
|
|
486
|
+
agent_config=ag_cfg,
|
|
487
|
+
get_builtin_custom_tools_fn=get_builtin_cg_tools,
|
|
488
|
+
build_custom_tool_schemas_fn=build_cg_tool_schemas,
|
|
489
|
+
exec_custom_tool_fn=exec_cg_tool,
|
|
490
|
+
is_verbose=True,
|
|
491
|
+
)
|
|
492
|
+
res = agent.answer('List in table format the people whose names match "José Carlos".')
|
|
493
|
+
print(json.dumps(res, indent=2, ensure_ascii=False))
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
- `tests/6d_test_custom_tool_DOC_SQL.py`: similar to the previous example, but builds multiple queries (ticket details and associated emails) and uses `input_data` for interpolation.
|
|
497
|
+
|
|
498
|
+
```python
|
|
499
|
+
import json
|
|
500
|
+
from oskaragent.agent import Oskar
|
|
501
|
+
from oskaragent.agent_config import AgentConfig
|
|
502
|
+
from my_company_tools.agent_cg_tools import (
|
|
503
|
+
build_cg_tool_schemas,
|
|
504
|
+
exec_cg_tool,
|
|
505
|
+
get_builtin_cg_tools,
|
|
506
|
+
)
|
|
507
|
+
|
|
508
|
+
custom_tools_info = {
|
|
509
|
+
"get_support_case_info_tool": {
|
|
510
|
+
"func_name": "query_database_tool",
|
|
511
|
+
"description": "Retrieve details of a technical support case.",
|
|
512
|
+
"connection_string": "...",
|
|
513
|
+
"title": "ITSM Support Case",
|
|
514
|
+
"queries": [
|
|
515
|
+
{"title": "Case", "query": "select top 1 CH.NumeroChamado ... where CH.NumeroChamado = '{KEY}'"},
|
|
516
|
+
{"title": "Emails", "query": "select CH.NumeroChamado, MAIL.Assunto ... where CH.NumeroChamado = '{KEY}'"},
|
|
517
|
+
],
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
ag_cfg = AgentConfig(custom_tools=custom_tools_info, model_settings={"history_window_size": 5})
|
|
521
|
+
agent = Oskar(
|
|
522
|
+
agent_config=ag_cfg,
|
|
523
|
+
input_data={"ticket": 42555},
|
|
524
|
+
get_builtin_custom_tools_fn=get_builtin_cg_tools,
|
|
525
|
+
build_custom_tool_schemas_fn=build_cg_tool_schemas,
|
|
526
|
+
exec_custom_tool_fn=exec_cg_tool,
|
|
527
|
+
is_verbose=True,
|
|
528
|
+
)
|
|
529
|
+
res = agent.answer("Provide a synthesis of ticket {ticket}.")
|
|
530
|
+
print(json.dumps(res, indent=2, ensure_ascii=False))
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
### 7. Analytics and BI
|
|
534
|
+
|
|
535
|
+
- `tests/7a_test_BI_CSV.py`: uses `working_files` pointing to `tests/sources/Basileia.csv` and requests an analysis with a chart generated by the Python tool.
|
|
536
|
+
|
|
537
|
+
```python
|
|
538
|
+
import json
|
|
539
|
+
from oskaragent.agent import Oskar
|
|
540
|
+
from oskaragent.agent_config import AgentConfig
|
|
541
|
+
|
|
542
|
+
ag_cfg = AgentConfig(
|
|
543
|
+
working_files=[
|
|
544
|
+
{
|
|
545
|
+
"name": "basileia",
|
|
546
|
+
"description": "Temperature data from the city of Basel",
|
|
547
|
+
"pathname": "./sources/Basileia.csv",
|
|
548
|
+
}
|
|
549
|
+
],
|
|
550
|
+
)
|
|
551
|
+
agent = Oskar(agent_config=ag_cfg, is_verbose=True)
|
|
552
|
+
res = agent.answer(
|
|
553
|
+
"Create a line chart showing the evolution of the average temperature over the years."
|
|
554
|
+
)
|
|
555
|
+
print(json.dumps(res, indent=2, ensure_ascii=False))
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
- `tests/7b_test_BI_SQL.py`: provisions a relational database via `working_databases`, generates a CSV in the session folder, and performs visualizations on the imported data.
|
|
559
|
+
|
|
560
|
+
```python
|
|
561
|
+
import json
|
|
562
|
+
from oskaragent.agent import Oskar
|
|
563
|
+
from oskaragent.agent_config import AgentConfig
|
|
564
|
+
|
|
565
|
+
ag_cfg = AgentConfig(
|
|
566
|
+
working_databases=[
|
|
567
|
+
{
|
|
568
|
+
"name": "Tickets",
|
|
569
|
+
"description": "Information about technical support tickets",
|
|
570
|
+
"connection_string": "Driver={ODBC Driver 17 for SQL Server};Server=CGSQL07;Database=DB_KPI;Uid=relkpi;Pwd=tele13",
|
|
571
|
+
"query": "select top 100 CH.NumeroChamado ...",
|
|
572
|
+
}
|
|
573
|
+
],
|
|
574
|
+
)
|
|
575
|
+
agent = Oskar(agent_config=ag_cfg, is_verbose=True)
|
|
576
|
+
res = agent.answer("Create a bar chart by Manufacturer.")
|
|
577
|
+
print(json.dumps(res, indent=2, ensure_ascii=False))
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
---
|
|
581
|
+
|
|
582
|
+
## Best Practices
|
|
583
|
+
|
|
584
|
+
- Use `is_verbose=True` during development to track tool calls and token usage.
|
|
585
|
+
|
|
586
|
+
- Always instruct the agent via `system_prompt` when a tool must be prioritized or when specific policies apply.
|
|
587
|
+
|
|
588
|
+
- Remember to name files generated by responses following the pattern `<message_id>-description.ext`; the `answer` method automatically collects those artifacts.
|
|
589
|
+
|
|
590
|
+
With these examples, you can adapt the `Oskar` class to any workflow: support, BI, corporate integrations, multi-agent setups, and multimodal artifact generation.
|
|
591
|
+
|
|
592
|
+
---
|
|
593
|
+
|
|
594
|
+
## Dependencies (`requirements.txt`)
|
|
595
|
+
|
|
596
|
+
The libraries below are versioned exactly as in `requirements.txt` and cover the minimum stack required to run the agent and tools.
|
|
597
|
+
|
|
598
|
+
### Core agent + Knowledge Base
|
|
599
|
+
|
|
600
|
+
openai==2.7.1
|
|
601
|
+
faiss-cpu==1.12.0
|
|
602
|
+
|
|
603
|
+
### Data tools used by `execute_python_code_tool`
|
|
604
|
+
|
|
605
|
+
pandas==2.3.0
|
|
606
|
+
numpy==2.3.4
|
|
607
|
+
seaborn==0.13.2
|
|
608
|
+
matplotlib==3.10.7
|
|
609
|
+
tabulate==0.9.0 (necessário para `DataFrame.to_markdown`)
|
|
610
|
+
|
|
611
|
+
### Document conversion and generation
|
|
612
|
+
|
|
613
|
+
pypdf==6.1.3
|
|
614
|
+
pdfkit==1.0.0 (requer `wkhtmltopdf` instalado)
|
|
615
|
+
pdfminer.six==20250506
|
|
616
|
+
python-docx==1.2.0
|
|
617
|
+
markdown2==2.5.4
|
|
618
|
+
beautifulsoup4==4.14.2
|
|
619
|
+
|
|
620
|
+
### External integrations
|
|
621
|
+
|
|
622
|
+
simple-salesforce==1.12.9
|
|
623
|
+
|
|
624
|
+
### Misc utilities
|
|
625
|
+
|
|
626
|
+
pyodbc==5.3.0
|
|
627
|
+
PyYAML==6.0.3
|
|
628
|
+
colorama==0.4.6
|