langchain-maritaca 0.2.2__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,289 @@
1
+ """DeepInfra Embeddings for use with Maritaca AI workflows.
2
+
3
+ Maritaca AI recommends DeepInfra's multilingual-e5-large model for embeddings
4
+ in RAG (Retrieval-Augmented Generation) workflows with Sabiá models.
5
+
6
+ Author: Anderson Henrique da Silva
7
+ Location: Minas Gerais, Brasil
8
+ GitHub: https://github.com/anderson-ufrj
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ from typing import Any
14
+
15
+ import httpx
16
+ from langchain_core.embeddings import Embeddings
17
+ from langchain_core.utils import from_env, secret_from_env
18
+ from pydantic import BaseModel, ConfigDict, Field, SecretStr, model_validator
19
+ from typing_extensions import Self
20
+
21
+ from langchain_maritaca.version import __version__
22
+
23
+ # Default embedding model recommended by Maritaca AI
24
+ DEFAULT_MODEL = "intfloat/multilingual-e5-large"
25
+ DEFAULT_API_BASE = "https://api.deepinfra.com/v1/openai"
26
+
27
+
28
+ class DeepInfraEmbeddings(BaseModel, Embeddings):
29
+ """DeepInfra embeddings integration for Maritaca AI workflows.
30
+
31
+ DeepInfra provides the multilingual-e5-large model, which is recommended
32
+ by Maritaca AI for RAG workflows with their Sabiá models. This model
33
+ supports 100 languages including Portuguese.
34
+
35
+ To use, you should have the environment variable `DEEPINFRA_API_KEY`
36
+ set with your API key, or pass it as a named parameter to the constructor.
37
+
38
+ Setup:
39
+ Install `langchain-maritaca` and set environment variable
40
+ `DEEPINFRA_API_KEY`.
41
+
42
+ ```bash
43
+ pip install -U langchain-maritaca
44
+ export DEEPINFRA_API_KEY="your-api-key"
45
+ ```
46
+
47
+ Key init args:
48
+ model:
49
+ Name of embedding model to use. Default is
50
+ `intfloat/multilingual-e5-large`.
51
+ api_key:
52
+ DeepInfra API key. If not passed in will be read from
53
+ env var `DEEPINFRA_API_KEY`.
54
+
55
+ Instantiate:
56
+ ```python
57
+ from langchain_maritaca import DeepInfraEmbeddings
58
+
59
+ embeddings = DeepInfraEmbeddings()
60
+ ```
61
+
62
+ Embed single text:
63
+ ```python
64
+ vector = embeddings.embed_query("Olá, como vai você?")
65
+ print(len(vector)) # 1024
66
+ ```
67
+
68
+ Embed multiple texts:
69
+ ```python
70
+ vectors = embeddings.embed_documents([
71
+ "Primeiro documento",
72
+ "Segundo documento",
73
+ ])
74
+ print(len(vectors)) # 2
75
+ print(len(vectors[0])) # 1024
76
+ ```
77
+
78
+ Use with Maritaca for RAG:
79
+ ```python
80
+ from langchain_maritaca import ChatMaritaca, DeepInfraEmbeddings
81
+ from langchain_community.vectorstores import FAISS
82
+
83
+ embeddings = DeepInfraEmbeddings()
84
+ vectorstore = FAISS.from_texts(documents, embeddings)
85
+
86
+ llm = ChatMaritaca()
87
+ # ... build your RAG chain
88
+ ```
89
+ """
90
+
91
+ client: Any = Field(default=None, exclude=True)
92
+ """Sync HTTP client."""
93
+
94
+ async_client: Any = Field(default=None, exclude=True)
95
+ """Async HTTP client."""
96
+
97
+ model: str = Field(default=DEFAULT_MODEL)
98
+ """Model name to use.
99
+
100
+ Default is `intfloat/multilingual-e5-large`, which is optimized for
101
+ multilingual text including Portuguese. Supports 100 languages.
102
+ Embedding dimension: 1024, max tokens: 512.
103
+ """
104
+
105
+ deepinfra_api_key: SecretStr | None = Field(
106
+ alias="api_key",
107
+ default_factory=secret_from_env("DEEPINFRA_API_KEY", default=None),
108
+ )
109
+ """DeepInfra API key. Automatically inferred from env var `DEEPINFRA_API_KEY`."""
110
+
111
+ deepinfra_api_base: str = Field(
112
+ alias="base_url",
113
+ default_factory=from_env("DEEPINFRA_API_BASE", default=DEFAULT_API_BASE),
114
+ )
115
+ """Base URL for DeepInfra API."""
116
+
117
+ request_timeout: float | None = Field(default=60.0, alias="timeout")
118
+ """Timeout for requests in seconds."""
119
+
120
+ max_retries: int = 2
121
+ """Maximum number of retries."""
122
+
123
+ batch_size: int = 32
124
+ """Maximum number of texts to embed in a single request."""
125
+
126
+ model_config = ConfigDict(
127
+ populate_by_name=True,
128
+ )
129
+
130
+ @model_validator(mode="after")
131
+ def validate_environment(self) -> Self:
132
+ """Validate that API key exists and initialize HTTP clients."""
133
+ api_key = (
134
+ self.deepinfra_api_key.get_secret_value()
135
+ if self.deepinfra_api_key
136
+ else ""
137
+ )
138
+ headers = {
139
+ "Authorization": f"Bearer {api_key}",
140
+ "Content-Type": "application/json",
141
+ "User-Agent": f"langchain-maritaca/{__version__}",
142
+ }
143
+
144
+ if not self.client:
145
+ self.client = httpx.Client(
146
+ base_url=self.deepinfra_api_base,
147
+ headers=headers,
148
+ timeout=httpx.Timeout(self.request_timeout),
149
+ )
150
+
151
+ if not self.async_client:
152
+ self.async_client = httpx.AsyncClient(
153
+ base_url=self.deepinfra_api_base,
154
+ headers=headers,
155
+ timeout=httpx.Timeout(self.request_timeout),
156
+ )
157
+
158
+ return self
159
+
160
+ def embed_documents(self, texts: list[str]) -> list[list[float]]:
161
+ """Embed a list of documents using DeepInfra.
162
+
163
+ Args:
164
+ texts: The list of texts to embed.
165
+
166
+ Returns:
167
+ List of embeddings, one for each text.
168
+ """
169
+ embeddings: list[list[float]] = []
170
+
171
+ # Process in batches
172
+ for i in range(0, len(texts), self.batch_size):
173
+ batch = texts[i : i + self.batch_size]
174
+ batch_embeddings = self._embed_batch(batch)
175
+ embeddings.extend(batch_embeddings)
176
+
177
+ return embeddings
178
+
179
+ def embed_query(self, text: str) -> list[float]:
180
+ """Embed a single query text.
181
+
182
+ Args:
183
+ text: The text to embed.
184
+
185
+ Returns:
186
+ Embedding for the text.
187
+ """
188
+ return self.embed_documents([text])[0]
189
+
190
+ async def aembed_documents(self, texts: list[str]) -> list[list[float]]:
191
+ """Async embed a list of documents using DeepInfra.
192
+
193
+ Args:
194
+ texts: The list of texts to embed.
195
+
196
+ Returns:
197
+ List of embeddings, one for each text.
198
+ """
199
+ embeddings: list[list[float]] = []
200
+
201
+ # Process in batches
202
+ for i in range(0, len(texts), self.batch_size):
203
+ batch = texts[i : i + self.batch_size]
204
+ batch_embeddings = await self._aembed_batch(batch)
205
+ embeddings.extend(batch_embeddings)
206
+
207
+ return embeddings
208
+
209
+ async def aembed_query(self, text: str) -> list[float]:
210
+ """Async embed a single query text.
211
+
212
+ Args:
213
+ text: The text to embed.
214
+
215
+ Returns:
216
+ Embedding for the text.
217
+ """
218
+ result = await self.aembed_documents([text])
219
+ return result[0]
220
+
221
+ def _embed_batch(self, texts: list[str]) -> list[list[float]]:
222
+ """Embed a batch of texts synchronously.
223
+
224
+ Args:
225
+ texts: List of texts to embed.
226
+
227
+ Returns:
228
+ List of embeddings.
229
+ """
230
+ payload = {
231
+ "input": texts,
232
+ "model": self.model,
233
+ "encoding_format": "float",
234
+ }
235
+
236
+ for attempt in range(self.max_retries + 1):
237
+ try:
238
+ response = self.client.post("/embeddings", json=payload)
239
+ response.raise_for_status()
240
+ data = response.json()
241
+ # Sort by index to ensure correct order
242
+ sorted_data = sorted(data["data"], key=lambda x: x["index"])
243
+ return [item["embedding"] for item in sorted_data]
244
+ except httpx.TimeoutException:
245
+ if attempt < self.max_retries:
246
+ continue
247
+ raise
248
+ except httpx.HTTPStatusError:
249
+ if attempt < self.max_retries:
250
+ continue
251
+ raise
252
+
253
+ msg = f"Failed after {self.max_retries + 1} attempts"
254
+ raise RuntimeError(msg)
255
+
256
+ async def _aembed_batch(self, texts: list[str]) -> list[list[float]]:
257
+ """Embed a batch of texts asynchronously.
258
+
259
+ Args:
260
+ texts: List of texts to embed.
261
+
262
+ Returns:
263
+ List of embeddings.
264
+ """
265
+ payload = {
266
+ "input": texts,
267
+ "model": self.model,
268
+ "encoding_format": "float",
269
+ }
270
+
271
+ for attempt in range(self.max_retries + 1):
272
+ try:
273
+ response = await self.async_client.post("/embeddings", json=payload)
274
+ response.raise_for_status()
275
+ data = response.json()
276
+ # Sort by index to ensure correct order
277
+ sorted_data = sorted(data["data"], key=lambda x: x["index"])
278
+ return [item["embedding"] for item in sorted_data]
279
+ except httpx.TimeoutException:
280
+ if attempt < self.max_retries:
281
+ continue
282
+ raise
283
+ except httpx.HTTPStatusError:
284
+ if attempt < self.max_retries:
285
+ continue
286
+ raise
287
+
288
+ msg = f"Failed after {self.max_retries + 1} attempts"
289
+ raise RuntimeError(msg)
File without changes
@@ -0,0 +1,7 @@
1
+ """Version information for langchain-maritaca.
2
+
3
+ Author: Anderson Henrique da Silva
4
+ Location: Minas Gerais, Brasil
5
+ """
6
+
7
+ __version__ = "0.2.2"
@@ -0,0 +1,274 @@
1
+ Metadata-Version: 2.4
2
+ Name: langchain-maritaca
3
+ Version: 0.2.2
4
+ Summary: An integration package connecting Maritaca AI and LangChain for Brazilian Portuguese language models
5
+ Project-URL: Homepage, https://github.com/anderson-ufrj/langchain-maritaca
6
+ Project-URL: Documentation, https://github.com/anderson-ufrj/langchain-maritaca#readme
7
+ Project-URL: Repository, https://github.com/anderson-ufrj/langchain-maritaca
8
+ Project-URL: Issues, https://github.com/anderson-ufrj/langchain-maritaca/issues
9
+ Project-URL: Changelog, https://github.com/anderson-ufrj/langchain-maritaca/blob/main/CHANGELOG.md
10
+ Project-URL: Maritaca AI, https://www.maritaca.ai/
11
+ Author-email: Anderson Henrique da Silva <andersonhs27@gmail.com>
12
+ License: MIT
13
+ License-File: LICENSE
14
+ Keywords: ai,brazilian,chatbot,langchain,llm,maritaca,nlp,portuguese,sabia
15
+ Classifier: Development Status :: 4 - Beta
16
+ Classifier: Intended Audience :: Developers
17
+ Classifier: License :: OSI Approved :: MIT License
18
+ Classifier: Operating System :: OS Independent
19
+ Classifier: Programming Language :: Python :: 3
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Programming Language :: Python :: 3.13
24
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
25
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
26
+ Requires-Python: <4.0,>=3.10
27
+ Requires-Dist: httpx<1.0.0,>=0.25.0
28
+ Requires-Dist: langchain-core<1.0.0,>=0.3.0
29
+ Provides-Extra: dev
30
+ Requires-Dist: mypy<2.0.0,>=1.10.0; extra == 'dev'
31
+ Requires-Dist: pre-commit<5.0.0,>=3.0.0; extra == 'dev'
32
+ Requires-Dist: pytest-asyncio<1.0.0,>=0.21.1; extra == 'dev'
33
+ Requires-Dist: pytest-cov<6.0.0,>=4.0.0; extra == 'dev'
34
+ Requires-Dist: pytest-mock<4.0.0,>=3.10.0; extra == 'dev'
35
+ Requires-Dist: pytest<9.0.0,>=7.3.0; extra == 'dev'
36
+ Requires-Dist: respx<1.0.0,>=0.20.0; extra == 'dev'
37
+ Requires-Dist: ruff<1.0.0,>=0.8.0; extra == 'dev'
38
+ Provides-Extra: test
39
+ Requires-Dist: pytest-asyncio<1.0.0,>=0.21.1; extra == 'test'
40
+ Requires-Dist: pytest-cov<6.0.0,>=4.0.0; extra == 'test'
41
+ Requires-Dist: pytest-mock<4.0.0,>=3.10.0; extra == 'test'
42
+ Requires-Dist: pytest<9.0.0,>=7.3.0; extra == 'test'
43
+ Requires-Dist: respx<1.0.0,>=0.20.0; extra == 'test'
44
+ Description-Content-Type: text/markdown
45
+
46
+ # langchain-maritaca
47
+
48
+ [![PyPI version](https://img.shields.io/pypi/v/langchain-maritaca.svg)](https://pypi.org/project/langchain-maritaca/)
49
+ [![Python](https://img.shields.io/pypi/pyversions/langchain-maritaca.svg)](https://pypi.org/project/langchain-maritaca/)
50
+ [![Downloads](https://img.shields.io/pypi/dm/langchain-maritaca.svg)](https://pypi.org/project/langchain-maritaca/)
51
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
52
+ [![CI](https://github.com/anderson-ufrj/langchain-maritaca/actions/workflows/ci.yml/badge.svg)](https://github.com/anderson-ufrj/langchain-maritaca/actions/workflows/ci.yml)
53
+
54
+ An integration package connecting [Maritaca AI](https://www.maritaca.ai/) and [LangChain](https://langchain.com/) for Brazilian Portuguese language models.
55
+
56
+ **Author:** Anderson Henrique da Silva
57
+ **Location:** Minas Gerais, Brasil
58
+ **GitHub:** [anderson-ufrj](https://github.com/anderson-ufrj)
59
+
60
+ ## Overview
61
+
62
+ Maritaca AI provides state-of-the-art Brazilian Portuguese language models, including the Sabiá family of models. This integration allows you to use Maritaca's models seamlessly within the LangChain ecosystem.
63
+
64
+ ### Available Models
65
+
66
+ | Model | Description | Pricing (per 1M tokens) |
67
+ |-------|-------------|------------------------|
68
+ | `sabia-3.1.1` | Most capable model, best for complex tasks | Check [Maritaca AI](https://www.maritaca.ai/) for pricing |
69
+ | `sabiazinho-3.1` | Fast and economical, great for simple tasks | Check [Maritaca AI](https://www.maritaca.ai/) for pricing |
70
+
71
+ ## Installation
72
+
73
+ ```bash
74
+ pip install langchain-maritaca
75
+ ```
76
+
77
+ ## Setup
78
+
79
+ Set your Maritaca API key as an environment variable:
80
+
81
+ ```bash
82
+ export MARITACA_API_KEY="your-api-key"
83
+ ```
84
+
85
+ Or pass it directly to the model:
86
+
87
+ ```python
88
+ from langchain_maritaca import ChatMaritaca
89
+
90
+ model = ChatMaritaca(api_key="your-api-key")
91
+ ```
92
+
93
+ ## Usage
94
+
95
+ ### Basic Usage
96
+
97
+ ```python
98
+ from langchain_maritaca import ChatMaritaca
99
+
100
+ model = ChatMaritaca(
101
+ model="sabia-3.1",
102
+ temperature=0.7,
103
+ )
104
+
105
+ messages = [
106
+ ("system", "Você é um assistente prestativo especializado em cultura brasileira."),
107
+ ("human", "Quais são as principais festas populares do Brasil?"),
108
+ ]
109
+
110
+ response = model.invoke(messages)
111
+ print(response.content)
112
+ ```
113
+
114
+ ### Streaming
115
+
116
+ ```python
117
+ from langchain_maritaca import ChatMaritaca
118
+
119
+ model = ChatMaritaca(model="sabia-3.1", streaming=True)
120
+
121
+ for chunk in model.stream("Conte uma história sobre o folclore brasileiro"):
122
+ print(chunk.content, end="", flush=True)
123
+ ```
124
+
125
+ ### Async Usage
126
+
127
+ ```python
128
+ import asyncio
129
+ from langchain_maritaca import ChatMaritaca
130
+
131
+ async def main():
132
+ model = ChatMaritaca(model="sabia-3.1")
133
+ response = await model.ainvoke("Qual é a receita de pão de queijo?")
134
+ print(response.content)
135
+
136
+ asyncio.run(main())
137
+ ```
138
+
139
+ ### With LangChain Expression Language (LCEL)
140
+
141
+ ```python
142
+ from langchain_maritaca import ChatMaritaca
143
+ from langchain_core.prompts import ChatPromptTemplate
144
+
145
+ model = ChatMaritaca(model="sabia-3.1")
146
+
147
+ prompt = ChatPromptTemplate.from_messages([
148
+ ("system", "Você é um especialista em {topic}."),
149
+ ("human", "{question}"),
150
+ ])
151
+
152
+ chain = prompt | model
153
+
154
+ response = chain.invoke({
155
+ "topic": "história do Brasil",
156
+ "question": "Quem foi Tiradentes?"
157
+ })
158
+ print(response.content)
159
+ ```
160
+
161
+ ### With Tool Calling (Function Calling)
162
+
163
+ ```python
164
+ from langchain_maritaca import ChatMaritaca
165
+ from langchain_core.tools import tool
166
+
167
+ @tool
168
+ def get_weather(city: str) -> str:
169
+ """Get the current weather for a city."""
170
+ return f"O clima em {city} está ensolarado, 25°C"
171
+
172
+ model = ChatMaritaca(model="sabia-3.1")
173
+ model_with_tools = model.bind_tools([get_weather])
174
+
175
+ response = model_with_tools.invoke("Como está o tempo em São Paulo?")
176
+ print(response)
177
+ ```
178
+
179
+ ## Why Maritaca AI?
180
+
181
+ Maritaca AI models are specifically trained for Brazilian Portuguese, offering:
182
+
183
+ - **Native Portuguese Understanding**: Better comprehension of Brazilian idioms, expressions, and cultural context
184
+ - **Local Data Training**: Trained on diverse Brazilian Portuguese data sources
185
+ - **Cost-Effective**: Competitive pricing for Portuguese language tasks
186
+ - **Low Latency**: Servers located in Brazil for faster response times
187
+
188
+ ## Used in Production
189
+
190
+ **[Cidadão.AI](https://cidadao-ai-frontend.vercel.app/pt)** - Brazilian government transparency platform powered by AI agents, handling 331K+ requests/month.
191
+
192
+ - Frontend: [github.com/anderson-ufrj/cidadao.ai-frontend](https://github.com/anderson-ufrj/cidadao.ai-frontend)
193
+ - Backend: [github.com/anderson-ufrj/cidadao.ai-backend](https://github.com/anderson-ufrj/cidadao.ai-backend)
194
+
195
+ > *Using this package in production? [Open an issue](https://github.com/anderson-ufrj/langchain-maritaca/issues) to get featured!*
196
+
197
+ ## API Reference
198
+
199
+ ### ChatMaritaca
200
+
201
+ Main class for interacting with Maritaca AI models.
202
+
203
+ **Parameters:**
204
+
205
+ | Parameter | Type | Default | Description |
206
+ |-----------|------|---------|-------------|
207
+ | `model` | str | `"sabia-3.1"` | Model name to use |
208
+ | `temperature` | float | `0.7` | Sampling temperature (0.0-2.0) |
209
+ | `max_tokens` | int | None | Maximum tokens to generate |
210
+ | `top_p` | float | `0.9` | Top-p sampling parameter |
211
+ | `api_key` | str | None | Maritaca API key (or use env var) |
212
+ | `base_url` | str | `"https://chat.maritaca.ai/api"` | API base URL |
213
+ | `timeout` | float | `60.0` | Request timeout in seconds |
214
+ | `max_retries` | int | `2` | Maximum retry attempts |
215
+ | `streaming` | bool | `False` | Enable streaming responses |
216
+
217
+ ## Development
218
+
219
+ ### Setup
220
+
221
+ ```bash
222
+ # Clone the repository
223
+ git clone https://github.com/anderson-ufrj/langchain-maritaca.git
224
+ cd langchain-maritaca
225
+
226
+ # Install dependencies
227
+ pip install -e ".[dev]"
228
+
229
+ # Run tests
230
+ pytest
231
+
232
+ # Run linting
233
+ ruff check .
234
+ ruff format .
235
+
236
+ # Run type checking
237
+ mypy langchain_maritaca
238
+ ```
239
+
240
+ ### Running Tests
241
+
242
+ ```bash
243
+ # Unit tests only
244
+ pytest tests/unit_tests/
245
+
246
+ # Integration tests (requires MARITACA_API_KEY)
247
+ pytest tests/integration_tests/
248
+
249
+ # With coverage
250
+ pytest --cov=langchain_maritaca --cov-report=html
251
+ ```
252
+
253
+ ## Contributing
254
+
255
+ Contributions are welcome! Please feel free to submit a Pull Request.
256
+
257
+ 1. Fork the repository
258
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
259
+ 3. Commit your changes (`git commit -m 'feat: add amazing feature'`)
260
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
261
+ 5. Open a Pull Request
262
+
263
+ ## Changelog
264
+
265
+ See [CHANGELOG.md](CHANGELOG.md) for a list of changes.
266
+
267
+ ## License
268
+
269
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
270
+
271
+ ## Related Projects
272
+
273
+ - [LangChain](https://github.com/langchain-ai/langchain) - Building applications with LLMs through composability
274
+ - [Maritaca AI](https://www.maritaca.ai/) - Brazilian Portuguese language models
@@ -0,0 +1,9 @@
1
+ langchain_maritaca/__init__.py,sha256=0YAmJnHRe5NI-9ryokPZESwenDawi131C-RGAs0WAv4,460
2
+ langchain_maritaca/chat_models.py,sha256=40sIcM57rlvIS_oW_In-U31EVHGOJid9SBXT-m4fMQU,28242
3
+ langchain_maritaca/embeddings.py,sha256=0gFcqYciTOMvgKrHEdKAcA1ikCQ_HyfikJRpesSG3_k,9003
4
+ langchain_maritaca/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ langchain_maritaca/version.py,sha256=9FDRquReMRUwtyEEI5Of7v2AnOUhBF8AsSwmJMqQRAU,141
6
+ langchain_maritaca-0.2.2.dist-info/METADATA,sha256=qsNgbWoUCHF3dBgvL_qdkglZl4M1PjidUb3rwmb-Hu8,9042
7
+ langchain_maritaca-0.2.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
8
+ langchain_maritaca-0.2.2.dist-info/licenses/LICENSE,sha256=lvL7E7mqeANCoUEkZDWPeqW6YckPG0FVi920ibuZlA0,1083
9
+ langchain_maritaca-0.2.2.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.28.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Anderson Henrique da Silva
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.