# 🤖 UltraGPT
**A powerful and modular library for advanced AI-based reasoning and step pipelines with multi-provider support**
[](https://python.org)
[](LICENSE.rst)
[](https://openai.com)
[](https://anthropic.com)
## 🌟 Features
- **🔄 Multi-Provider Support:** Use OpenAI and Anthropic Claude models seamlessly
- **📝 Steps Pipeline:** Break down complex tasks into manageable steps
- **🧠 Reasoning Pipeline:** Advanced multi-iteration reasoning capabilities
- **🛠️ Tool Integration:** Web search, calculator, math operations, and custom tools
- **🎯 Structured Output:** Get structured responses using Pydantic schemas
- **🔧 Tool Calling:** Execute custom tools with validated parameters
- **📊 Token Management:** Comprehensive token tracking across providers
## 📦 Installation
```bash
pip install ultragpt
# For environment variable support (optional)
pip install python-dotenv
```
**Note:** Starting with version 4.0.0, Anthropic Claude support is included by default!
## 🚀 Quick Start
### Basic Usage (OpenAI)
```python
from ultragpt import UltraGPT
# Initialize with OpenAI (default)
ultragpt = UltraGPT(api_key="your-openai-api-key")
# Simple chat
response, tokens, details = ultragpt.chat([
{"role": "user", "content": "Write a story about an elephant."}
])
print("Response:", response)
print("Tokens used:", tokens)
```
### Multi-Provider Support
```python
from ultragpt import UltraGPT
# OpenAI (default)
ultragpt_openai = UltraGPT(api_key="your-openai-api-key")
# Claude
ultragpt_claude = UltraGPT(
api_key="your-anthropic-api-key",
provider="anthropic"
)
# Both work the same way!
response, tokens, details = ultragpt_claude.chat([
{"role": "user", "content": "Hello Claude!"}
])
```
### Provider:Model Format
```python
# Use provider:model format for specific models
ultragpt = UltraGPT(
api_key="your-openai-api-key",
claude_api_key="your-anthropic-api-key" # For Claude models
)
# OpenAI models
response = ultragpt.chat([
{"role": "user", "content": "Hello!"}
], model="openai:gpt-4o")
# Claude models
response = ultragpt.chat([
{"role": "user", "content": "Hello!"}
], model="claude:claude-3-sonnet-20240229")
```
## 🌐 Web Search & Tools
### Google Search Integration
```python
from ultragpt import UltraGPT
ultragpt = UltraGPT(
api_key="your-openai-api-key",
google_api_key="your-google-api-key",
search_engine_id="your-search-engine-id"
)
# Web search with scraping
response = ultragpt.chat([
{"role": "user", "content": "What are the latest AI trends?"}
], tools=["web-search"], tools_config={
"web-search": {
"max_results": 3,
"enable_scraping": True,
"max_scrape_length": 2000
}
})
```
### Built-in Tools
```python
# Use multiple tools
response = ultragpt.chat([
{"role": "user", "content": "Calculate 15% of 200 and check if 17 is prime"}
], tools=["calculator", "math-operations"])
```
## 🔧 Custom Tool Calling
### Define Custom Tools
```python
from pydantic import BaseModel
from ultragpt.schemas import UserTool
class EmailParams(BaseModel):
recipient: str
subject: str
body: str
email_tool = UserTool(
name="send_email",
description="Send an email to a recipient",
parameters_schema=EmailParams,
usage_guide="Use when user wants to send an email",
when_to_use="When user asks to send an email"
)
# Use custom tools
response, tokens = ultragpt.tool_call(
messages=[{"role": "user", "content": "Send email to john@example.com about meeting"}],
user_tools=[email_tool]
)
```
## 🧠 Advanced Pipelines
### Steps Pipeline
```python
response = ultragpt.chat([
{"role": "user", "content": "Plan a trip to Japan for 2 weeks"}
], steps_pipeline=True, steps_model="gpt-4o-mini") # Use cheaper model for steps
```
### Reasoning Pipeline
```python
response = ultragpt.chat([
{"role": "user", "content": "Solve this complex problem: ..."}
], reasoning_pipeline=True, reasoning_iterations=5)
```
### Mixed Provider Pipelines
```python
# Use OpenAI for main response, Claude for reasoning
response = ultragpt.chat([
{"role": "user", "content": "Complex analysis task"}
],
model="openai:gpt-4o", # Main model
reasoning_model="claude:claude-3-sonnet-20240229", # Reasoning model
reasoning_pipeline=True
)
```
## 📊 Structured Output
### Using Pydantic Schemas
```python
from pydantic import BaseModel
class AnalysisResult(BaseModel):
sentiment: str
confidence: float
keywords: list[str]
# Get structured output (works with both providers)
result = ultragpt.chat_with_schema(
messages=[{"role": "user", "content": "Analyze: 'I love this product!'"}],
schema=AnalysisResult
)
print(result.sentiment) # "positive"
print(result.confidence) # 0.95
```
## 🔄 History Management
```python
# Enable conversation history tracking
ultragpt = UltraGPT(
api_key="your-api-key",
track_history=True,
max_history=50 # Keep last 50 messages
)
# Continue conversations naturally
response1 = ultragpt.chat([{"role": "user", "content": "My name is Alice"}])
response2 = ultragpt.chat([{"role": "user", "content": "What's my name?"}])
# Response2 will remember Alice from response1
```
## ⚙️ Configuration Options
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `api_key` | str | Required | OpenAI API key |
| `claude_api_key` | str | None | Anthropic API key (for Claude models) |
| `provider` | str | "openai" | Default provider ("openai" or "anthropic") |
| `model` | str | Auto-selected | Default model for provider |
| `temperature` | float | 0.7 | Output randomness (0-2) |
| `reasoning_iterations` | int | 3 | Number of reasoning steps |
| `tools` | list | [] | Enabled tools |
| `verbose` | bool | False | Enable detailed logging |
| `track_history` | bool | False | Enable conversation history |
| `max_history` | int | 100 | Maximum messages to keep |
## 🛠️ Available Tools
### Web Search
- **Google Custom Search** with result scraping
- Configurable result limits and scraping depth
- Error handling and rate limiting
### Calculator
- Mathematical expression evaluation
- Complex calculations with step-by-step solutions
- Support for scientific functions
### Math Operations
- Range checking and validation
- Statistical analysis and outlier detection
- Prime number checking and factorization
- Sequence analysis (arithmetic/geometric patterns)
- Percentage calculations and ratios
## 🌍 Environment Variables
Create a `.env` file for easy configuration:
```env
OPENAI_API_KEY=your-openai-api-key
ANTHROPIC_API_KEY=your-anthropic-api-key
GOOGLE_SEARCH_API_KEY=your-google-api-key
SEARCH_ENGINE_ID=your-search-engine-id
```
```python
from dotenv import load_dotenv
import os
load_dotenv()
ultragpt = UltraGPT(
api_key=os.getenv("OPENAI_API_KEY"),
claude_api_key=os.getenv("ANTHROPIC_API_KEY"),
google_api_key=os.getenv("GOOGLE_SEARCH_API_KEY"),
search_engine_id=os.getenv("SEARCH_ENGINE_ID")
)
```
## 📋 Requirements
- Python 3.6+
- OpenAI API key (for OpenAI models)
- Anthropic API key (for Claude models)
- Google Custom Search API (for web search tool)
**Built-in Dependencies:**
- `anthropic==0.60.0` - Claude API support (included by default)
- `openai>=1.59.3` - OpenAI API support
- `pydantic>=2.10.4` - Data validation and schemas
## 🚀 Examples
Check out the `examples/` directory for comprehensive usage examples:
- `example_tool_call.py` - Custom tool calling
- `example_claude_support.py` - Claude-specific features
- `example_multi_provider.py` - Multi-provider usage
- `example_history_control.py` - Conversation history
## 🤝 Contributing
Contributions are welcome! Please follow these steps:
1. Fork the repository
2. Create a feature branch (`git checkout -b feature/improvement`)
3. Make your changes
4. Add tests if applicable
5. Commit your changes (`git commit -am 'Add new feature'`)
6. Push to the branch (`git push origin feature/improvement`)
7. Open a Pull Request
## 📝 License
This project is licensed under the MIT License - see the [LICENSE.rst](LICENSE.rst) file for details.
## 👥 Author
**Ranit Bhowmick**
- Email: bhowmickranitking@duck.com
- GitHub: [@Kawai-Senpai](https://github.com/Kawai-Senpai)
## 🔗 Links
- [Documentation](docs/)
- [Examples](examples/)
- [Tests](tests/)
- [PyPI Package](https://pypi.org/project/ultragpt/)
---
<div align="center">
Made with ❤️ by Ranit Bhowmick
</div>
Raw data
{
"_id": null,
"home_page": "https://github.com/Kawai-Senpai/UltraGPT",
"name": "ultragpt",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.6",
"maintainer_email": null,
"keywords": "ai, gpt, openai, claude, anthropic, reasoning, pipeline, tools, multi-provider",
"author": "Ranit Bhowmick",
"author_email": "bhowmickranitking@duck.com",
"download_url": "https://files.pythonhosted.org/packages/62/8d/e156f2eb4815d23fd0147fea120015f36c6ba3f077c583d2bec9c370faac/ultragpt-4.1.0.tar.gz",
"platform": null,
"description": "# \ud83e\udd16 UltraGPT\r\n\r\n**A powerful and modular library for advanced AI-based reasoning and step pipelines with multi-provider support**\r\n\r\n[](https://python.org)\r\n[](LICENSE.rst)\r\n[](https://openai.com)\r\n[](https://anthropic.com)\r\n\r\n## \ud83c\udf1f Features\r\n\r\n- **\ud83d\udd04 Multi-Provider Support:** Use OpenAI and Anthropic Claude models seamlessly\r\n- **\ud83d\udcdd Steps Pipeline:** Break down complex tasks into manageable steps\r\n- **\ud83e\udde0 Reasoning Pipeline:** Advanced multi-iteration reasoning capabilities\r\n- **\ud83d\udee0\ufe0f Tool Integration:** Web search, calculator, math operations, and custom tools\r\n- **\ud83c\udfaf Structured Output:** Get structured responses using Pydantic schemas\r\n- **\ud83d\udd27 Tool Calling:** Execute custom tools with validated parameters\r\n- **\ud83d\udcca Token Management:** Comprehensive token tracking across providers\r\n\r\n## \ud83d\udce6 Installation\r\n\r\n```bash\r\npip install ultragpt\r\n\r\n# For environment variable support (optional)\r\npip install python-dotenv\r\n```\r\n\r\n**Note:** Starting with version 4.0.0, Anthropic Claude support is included by default!\r\n\r\n## \ud83d\ude80 Quick Start\r\n\r\n### Basic Usage (OpenAI)\r\n```python\r\nfrom ultragpt import UltraGPT\r\n\r\n# Initialize with OpenAI (default)\r\nultragpt = UltraGPT(api_key=\"your-openai-api-key\")\r\n\r\n# Simple chat\r\nresponse, tokens, details = ultragpt.chat([\r\n {\"role\": \"user\", \"content\": \"Write a story about an elephant.\"}\r\n])\r\nprint(\"Response:\", response)\r\nprint(\"Tokens used:\", tokens)\r\n```\r\n\r\n### Multi-Provider Support\r\n```python\r\nfrom ultragpt import UltraGPT\r\n\r\n# OpenAI (default)\r\nultragpt_openai = UltraGPT(api_key=\"your-openai-api-key\")\r\n\r\n# Claude\r\nultragpt_claude = UltraGPT(\r\n api_key=\"your-anthropic-api-key\", \r\n provider=\"anthropic\"\r\n)\r\n\r\n# Both work the same way!\r\nresponse, tokens, details = ultragpt_claude.chat([\r\n {\"role\": \"user\", \"content\": \"Hello Claude!\"}\r\n])\r\n```\r\n\r\n### Provider:Model Format\r\n```python\r\n# Use provider:model format for specific models\r\nultragpt = UltraGPT(\r\n api_key=\"your-openai-api-key\",\r\n claude_api_key=\"your-anthropic-api-key\" # For Claude models\r\n)\r\n\r\n# OpenAI models\r\nresponse = ultragpt.chat([\r\n {\"role\": \"user\", \"content\": \"Hello!\"}\r\n], model=\"openai:gpt-4o\")\r\n\r\n# Claude models \r\nresponse = ultragpt.chat([\r\n {\"role\": \"user\", \"content\": \"Hello!\"}\r\n], model=\"claude:claude-3-sonnet-20240229\")\r\n```\r\n\r\n## \ud83c\udf10 Web Search & Tools\r\n\r\n### Google Search Integration\r\n```python\r\nfrom ultragpt import UltraGPT\r\n\r\nultragpt = UltraGPT(\r\n api_key=\"your-openai-api-key\",\r\n google_api_key=\"your-google-api-key\",\r\n search_engine_id=\"your-search-engine-id\"\r\n)\r\n\r\n# Web search with scraping\r\nresponse = ultragpt.chat([\r\n {\"role\": \"user\", \"content\": \"What are the latest AI trends?\"}\r\n], tools=[\"web-search\"], tools_config={\r\n \"web-search\": {\r\n \"max_results\": 3,\r\n \"enable_scraping\": True,\r\n \"max_scrape_length\": 2000\r\n }\r\n})\r\n```\r\n\r\n### Built-in Tools\r\n```python\r\n# Use multiple tools\r\nresponse = ultragpt.chat([\r\n {\"role\": \"user\", \"content\": \"Calculate 15% of 200 and check if 17 is prime\"}\r\n], tools=[\"calculator\", \"math-operations\"])\r\n```\r\n\r\n## \ud83d\udd27 Custom Tool Calling\r\n\r\n### Define Custom Tools\r\n```python\r\nfrom pydantic import BaseModel\r\nfrom ultragpt.schemas import UserTool\r\n\r\nclass EmailParams(BaseModel):\r\n recipient: str\r\n subject: str\r\n body: str\r\n\r\nemail_tool = UserTool(\r\n name=\"send_email\",\r\n description=\"Send an email to a recipient\",\r\n parameters_schema=EmailParams,\r\n usage_guide=\"Use when user wants to send an email\",\r\n when_to_use=\"When user asks to send an email\"\r\n)\r\n\r\n# Use custom tools\r\nresponse, tokens = ultragpt.tool_call(\r\n messages=[{\"role\": \"user\", \"content\": \"Send email to john@example.com about meeting\"}],\r\n user_tools=[email_tool]\r\n)\r\n```\r\n\r\n## \ud83e\udde0 Advanced Pipelines\r\n\r\n### Steps Pipeline\r\n```python\r\nresponse = ultragpt.chat([\r\n {\"role\": \"user\", \"content\": \"Plan a trip to Japan for 2 weeks\"}\r\n], steps_pipeline=True, steps_model=\"gpt-4o-mini\") # Use cheaper model for steps\r\n```\r\n\r\n### Reasoning Pipeline\r\n```python\r\nresponse = ultragpt.chat([\r\n {\"role\": \"user\", \"content\": \"Solve this complex problem: ...\"}\r\n], reasoning_pipeline=True, reasoning_iterations=5)\r\n```\r\n\r\n### Mixed Provider Pipelines\r\n```python\r\n# Use OpenAI for main response, Claude for reasoning\r\nresponse = ultragpt.chat([\r\n {\"role\": \"user\", \"content\": \"Complex analysis task\"}\r\n], \r\nmodel=\"openai:gpt-4o\", # Main model\r\nreasoning_model=\"claude:claude-3-sonnet-20240229\", # Reasoning model\r\nreasoning_pipeline=True\r\n)\r\n```\r\n\r\n## \ud83d\udcca Structured Output\r\n\r\n### Using Pydantic Schemas\r\n```python\r\nfrom pydantic import BaseModel\r\n\r\nclass AnalysisResult(BaseModel):\r\n sentiment: str\r\n confidence: float\r\n keywords: list[str]\r\n\r\n# Get structured output (works with both providers)\r\nresult = ultragpt.chat_with_schema(\r\n messages=[{\"role\": \"user\", \"content\": \"Analyze: 'I love this product!'\"}],\r\n schema=AnalysisResult\r\n)\r\nprint(result.sentiment) # \"positive\"\r\nprint(result.confidence) # 0.95\r\n```\r\n\r\n## \ud83d\udd04 History Management\r\n\r\n```python\r\n# Enable conversation history tracking\r\nultragpt = UltraGPT(\r\n api_key=\"your-api-key\",\r\n track_history=True,\r\n max_history=50 # Keep last 50 messages\r\n)\r\n\r\n# Continue conversations naturally\r\nresponse1 = ultragpt.chat([{\"role\": \"user\", \"content\": \"My name is Alice\"}])\r\nresponse2 = ultragpt.chat([{\"role\": \"user\", \"content\": \"What's my name?\"}])\r\n# Response2 will remember Alice from response1\r\n```\r\n\r\n## \u2699\ufe0f Configuration Options\r\n\r\n| Parameter | Type | Default | Description |\r\n|-----------|------|---------|-------------|\r\n| `api_key` | str | Required | OpenAI API key |\r\n| `claude_api_key` | str | None | Anthropic API key (for Claude models) |\r\n| `provider` | str | \"openai\" | Default provider (\"openai\" or \"anthropic\") |\r\n| `model` | str | Auto-selected | Default model for provider |\r\n| `temperature` | float | 0.7 | Output randomness (0-2) |\r\n| `reasoning_iterations` | int | 3 | Number of reasoning steps |\r\n| `tools` | list | [] | Enabled tools |\r\n| `verbose` | bool | False | Enable detailed logging |\r\n| `track_history` | bool | False | Enable conversation history |\r\n| `max_history` | int | 100 | Maximum messages to keep |\r\n\r\n## \ud83d\udee0\ufe0f Available Tools\r\n\r\n### Web Search\r\n- **Google Custom Search** with result scraping\r\n- Configurable result limits and scraping depth\r\n- Error handling and rate limiting\r\n\r\n### Calculator\r\n- Mathematical expression evaluation\r\n- Complex calculations with step-by-step solutions\r\n- Support for scientific functions\r\n\r\n### Math Operations\r\n- Range checking and validation\r\n- Statistical analysis and outlier detection\r\n- Prime number checking and factorization\r\n- Sequence analysis (arithmetic/geometric patterns)\r\n- Percentage calculations and ratios\r\n\r\n## \ud83c\udf0d Environment Variables\r\n\r\nCreate a `.env` file for easy configuration:\r\n\r\n```env\r\nOPENAI_API_KEY=your-openai-api-key\r\nANTHROPIC_API_KEY=your-anthropic-api-key\r\nGOOGLE_SEARCH_API_KEY=your-google-api-key\r\nSEARCH_ENGINE_ID=your-search-engine-id\r\n```\r\n\r\n```python\r\nfrom dotenv import load_dotenv\r\nimport os\r\n\r\nload_dotenv()\r\n\r\nultragpt = UltraGPT(\r\n api_key=os.getenv(\"OPENAI_API_KEY\"),\r\n claude_api_key=os.getenv(\"ANTHROPIC_API_KEY\"),\r\n google_api_key=os.getenv(\"GOOGLE_SEARCH_API_KEY\"),\r\n search_engine_id=os.getenv(\"SEARCH_ENGINE_ID\")\r\n)\r\n```\r\n\r\n## \ud83d\udccb Requirements\r\n\r\n- Python 3.6+\r\n- OpenAI API key (for OpenAI models)\r\n- Anthropic API key (for Claude models)\r\n- Google Custom Search API (for web search tool)\r\n\r\n**Built-in Dependencies:**\r\n- `anthropic==0.60.0` - Claude API support (included by default)\r\n- `openai>=1.59.3` - OpenAI API support\r\n- `pydantic>=2.10.4` - Data validation and schemas\r\n\r\n## \ud83d\ude80 Examples\r\n\r\nCheck out the `examples/` directory for comprehensive usage examples:\r\n- `example_tool_call.py` - Custom tool calling\r\n- `example_claude_support.py` - Claude-specific features\r\n- `example_multi_provider.py` - Multi-provider usage\r\n- `example_history_control.py` - Conversation history\r\n\r\n## \ud83e\udd1d Contributing\r\n\r\nContributions are welcome! Please follow these steps:\r\n\r\n1. Fork the repository\r\n2. Create a feature branch (`git checkout -b feature/improvement`)\r\n3. Make your changes\r\n4. Add tests if applicable\r\n5. Commit your changes (`git commit -am 'Add new feature'`)\r\n6. Push to the branch (`git push origin feature/improvement`)\r\n7. Open a Pull Request\r\n\r\n## \ud83d\udcdd License\r\n\r\nThis project is licensed under the MIT License - see the [LICENSE.rst](LICENSE.rst) file for details.\r\n\r\n## \ud83d\udc65 Author\r\n\r\n**Ranit Bhowmick**\r\n- Email: bhowmickranitking@duck.com\r\n- GitHub: [@Kawai-Senpai](https://github.com/Kawai-Senpai)\r\n\r\n## \ud83d\udd17 Links\r\n\r\n- [Documentation](docs/)\r\n- [Examples](examples/)\r\n- [Tests](tests/)\r\n- [PyPI Package](https://pypi.org/project/ultragpt/)\r\n\r\n---\r\n\r\n<div align=\"center\">\r\nMade with \u2764\ufe0f by Ranit Bhowmick\r\n</div>\r\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "UltraGPT: A modular multi-provider AI library for advanced reasoning and step pipelines with OpenAI and Claude support",
"version": "4.1.0",
"project_urls": {
"Bug Reports": "https://github.com/Kawai-Senpai/UltraGPT/issues",
"Documentation": "https://github.com/Kawai-Senpai/UltraGPT/tree/main/docs",
"Homepage": "https://github.com/Kawai-Senpai/UltraGPT",
"Source": "https://github.com/Kawai-Senpai/UltraGPT"
},
"split_keywords": [
"ai",
" gpt",
" openai",
" claude",
" anthropic",
" reasoning",
" pipeline",
" tools",
" multi-provider"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "f1ececca32e5d18082eb1b2d703ea1509bc81a32f2f84a5ccec19af3e641b441",
"md5": "770f7bbd3543e16ccd563c964c302569",
"sha256": "ea03b3e0078b1608a1a68b60dde1e1b702e5fc30fc7dcccb77ea0b9c39193860"
},
"downloads": -1,
"filename": "ultragpt-4.1.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "770f7bbd3543e16ccd563c964c302569",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.6",
"size": 57693,
"upload_time": "2025-08-28T16:27:35",
"upload_time_iso_8601": "2025-08-28T16:27:35.370438Z",
"url": "https://files.pythonhosted.org/packages/f1/ec/ecca32e5d18082eb1b2d703ea1509bc81a32f2f84a5ccec19af3e641b441/ultragpt-4.1.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "628de156f2eb4815d23fd0147fea120015f36c6ba3f077c583d2bec9c370faac",
"md5": "0fec9f0cc9192182fa83891544814850",
"sha256": "aed79fa58513476b16cb2df7a577f279ad2063e4edeb827bac4be9e416166977"
},
"downloads": -1,
"filename": "ultragpt-4.1.0.tar.gz",
"has_sig": false,
"md5_digest": "0fec9f0cc9192182fa83891544814850",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.6",
"size": 57301,
"upload_time": "2025-08-28T16:27:36",
"upload_time_iso_8601": "2025-08-28T16:27:36.908929Z",
"url": "https://files.pythonhosted.org/packages/62/8d/e156f2eb4815d23fd0147fea120015f36c6ba3f077c583d2bec9c370faac/ultragpt-4.1.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-28 16:27:36",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "Kawai-Senpai",
"github_project": "UltraGPT",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [
{
"name": "openai",
"specs": [
[
"==",
"1.99.5"
]
]
},
{
"name": "ultraprint",
"specs": [
[
"==",
"3.2.0"
]
]
},
{
"name": "anthropic",
"specs": [
[
"==",
"0.60.0"
]
]
},
{
"name": "pydantic",
"specs": [
[
"==",
"2.10.4"
]
]
},
{
"name": "google-api-python-client",
"specs": [
[
">=",
"2.0.0"
]
]
},
{
"name": "requests",
"specs": [
[
">=",
"2.25.0"
]
]
},
{
"name": "beautifulsoup4",
"specs": [
[
">=",
"4.9.0"
]
]
},
{
"name": "readability-lxml",
"specs": [
[
">=",
"0.8.0"
]
]
},
{
"name": "lxml",
"specs": [
[
">=",
"4.6.0"
]
]
},
{
"name": "tiktoken",
"specs": [
[
">=",
"0.11.0"
]
]
}
],
"lcname": "ultragpt"
}