aisbf 0.1.0__py3-none-any.whl → 0.1.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,125 @@
1
+ """
2
+ Copyleft (C) 2026 Stefy Lanza <stefy@nexlab.net>
3
+
4
+ AISBF - AI Service Broker Framework || AI Should Be Free
5
+
6
+ Main application for AISBF.
7
+
8
+ This program is free software: you can redistribute it and/or modify
9
+ it under the terms of the GNU General Public License as published by
10
+ the Free Software Foundation, either version 3 of the License, or
11
+ (at your option) any later version.
12
+
13
+ This program is distributed in the hope that it will be useful,
14
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ GNU General Public License for more details.
17
+
18
+ You should have received a copy of the GNU General Public License
19
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
20
+
21
+ Why did the programmer quit his job? Because he didn't get arrays!
22
+
23
+ Main application for AISBF.
24
+ """
25
+ from fastapi import FastAPI, HTTPException, Request, status
26
+ from fastapi.responses import JSONResponse, StreamingResponse
27
+ from fastapi.middleware.cors import CORSMiddleware
28
+ from aisbf.models import ChatCompletionRequest, ChatCompletionResponse
29
+ from aisbf.handlers import RequestHandler, RotationHandler
30
+ from aisbf.config import config
31
+ import time
32
+ import logging
33
+ from datetime import datetime, timedelta
34
+ from collections import defaultdict
35
+
36
+ # Configure logging
37
+ logging.basicConfig(level=logging.DEBUG)
38
+ logger = logging.getLogger(__name__)
39
+
40
+ # Initialize handlers
41
+ request_handler = RequestHandler()
42
+ rotation_handler = RotationHandler()
43
+
44
+ app = FastAPI(title="AI Proxy Server")
45
+
46
+ # CORS middleware
47
+ app.add_middleware(
48
+ CORSMiddleware,
49
+ allow_origins=["*"],
50
+ allow_credentials=True,
51
+ allow_methods=["*"],
52
+ allow_headers=["*"],
53
+ )
54
+
55
+ @app.get("/")
56
+ async def root():
57
+ return {"message": "AI Proxy Server is running", "providers": list(config.providers.keys())}
58
+
59
+ @app.post("/api/{provider_id}/chat/completions")
60
+ async def chat_completions(provider_id: str, request: Request, body: ChatCompletionRequest):
61
+ logger.debug(f"Received chat_completions request for provider: {provider_id}")
62
+ logger.debug(f"Request headers: {dict(request.headers)}")
63
+ logger.debug(f"Request body: {body}")
64
+
65
+ body_dict = body.model_dump()
66
+
67
+ # Check if it's a rotation
68
+ if provider_id in config.rotations:
69
+ logger.debug("Handling rotation request")
70
+ return await rotation_handler.handle_rotation_request(provider_id, body_dict)
71
+
72
+ # Check if it's a provider
73
+ if provider_id not in config.providers:
74
+ logger.error(f"Provider {provider_id} not found")
75
+ raise HTTPException(status_code=400, detail=f"Provider {provider_id} not found")
76
+
77
+ provider_config = config.get_provider(provider_id)
78
+ logger.debug(f"Provider config: {provider_config}")
79
+
80
+ try:
81
+ if body.stream:
82
+ logger.debug("Handling streaming chat completion")
83
+ return await request_handler.handle_streaming_chat_completion(request, provider_id, body_dict)
84
+ else:
85
+ logger.debug("Handling non-streaming chat completion")
86
+ result = await request_handler.handle_chat_completion(request, provider_id, body_dict)
87
+ logger.debug(f"Response result: {result}")
88
+ return result
89
+ except Exception as e:
90
+ logger.error(f"Error handling chat_completions: {str(e)}", exc_info=True)
91
+ raise
92
+
93
+ @app.get("/api/{provider_id}/models")
94
+ async def list_models(request: Request, provider_id: str):
95
+ logger.debug(f"Received list_models request for provider: {provider_id}")
96
+
97
+ # Check if it's a rotation
98
+ if provider_id in config.rotations:
99
+ logger.debug("Handling rotation model list request")
100
+ return await rotation_handler.handle_rotation_model_list(provider_id)
101
+
102
+ # Check if it's a provider
103
+ if provider_id not in config.providers:
104
+ logger.error(f"Provider {provider_id} not found")
105
+ raise HTTPException(status_code=400, detail=f"Provider {provider_id} not found")
106
+
107
+ provider_config = config.get_provider(provider_id)
108
+
109
+ try:
110
+ logger.debug("Handling model list request")
111
+ result = await request_handler.handle_model_list(request, provider_id)
112
+ logger.debug(f"Models result: {result}")
113
+ return result
114
+ except Exception as e:
115
+ logger.error(f"Error handling list_models: {str(e)}", exc_info=True)
116
+ raise
117
+
118
+ def main():
119
+ """Main entry point for the AISBF server"""
120
+ import uvicorn
121
+ logger.info("Starting AI Proxy Server on http://localhost:8000")
122
+ uvicorn.run(app, host="0.0.0.0", port=8000)
123
+
124
+ if __name__ == "__main__":
125
+ main()
@@ -0,0 +1,156 @@
1
+ {
2
+ "providers": {
3
+ "gemini": {
4
+ "id": "gemini",
5
+ "name": "Google AI Studio",
6
+ "endpoint": "https://generativelanguage.googleapis.com/v1beta",
7
+ "type": "google",
8
+ "api_key_required": true,
9
+ "rate_limit": 0
10
+ },
11
+ "openai": {
12
+ "id": "openai",
13
+ "name": "OpenAI",
14
+ "endpoint": "https://api.openai.com/v1",
15
+ "type": "openai",
16
+ "api_key_required": true,
17
+ "rate_limit": 0
18
+ },
19
+ "anthropic": {
20
+ "id": "anthropic",
21
+ "name": "Anthropic",
22
+ "endpoint": "https://api.anthropic.com/v1",
23
+ "type": "anthropic",
24
+ "api_key_required": true,
25
+ "rate_limit": 0
26
+ },
27
+ "ollama": {
28
+ "id": "ollama",
29
+ "name": "Ollama",
30
+ "endpoint": "http://localhost:11434",
31
+ "type": "ollama",
32
+ "api_key_required": false,
33
+ "rate_limit": 0
34
+ },
35
+ "azure_openai": {
36
+ "id": "azure_openai",
37
+ "name": "Azure OpenAI",
38
+ "endpoint": "https://your-azure-endpoint.openai.azure.com",
39
+ "type": "openai",
40
+ "api_key_required": true,
41
+ "rate_limit": 0
42
+ },
43
+ "cohere": {
44
+ "id": "cohere",
45
+ "name": "Cohere",
46
+ "endpoint": "https://api.cohere.com/v1",
47
+ "type": "cohere",
48
+ "api_key_required": true,
49
+ "rate_limit": 0
50
+ },
51
+ "huggingface": {
52
+ "id": "huggingface",
53
+ "name": "Hugging Face",
54
+ "endpoint": "https://api-inference.huggingface.co",
55
+ "type": "huggingface",
56
+ "api_key_required": true,
57
+ "rate_limit": 0
58
+ },
59
+ "replicate": {
60
+ "id": "replicate",
61
+ "name": "Replicate",
62
+ "endpoint": "https://api.replicate.com/v1",
63
+ "type": "replicate",
64
+ "api_key_required": true,
65
+ "rate_limit": 0
66
+ },
67
+ "togetherai": {
68
+ "id": "togetherai",
69
+ "name": "Together AI",
70
+ "endpoint": "https://api.together.xyz/v1",
71
+ "type": "openai",
72
+ "api_key_required": true,
73
+ "rate_limit": 0
74
+ },
75
+ "groq": {
76
+ "id": "groq",
77
+ "name": "Groq",
78
+ "endpoint": "https://api.groq.com/openai/v1",
79
+ "type": "openai",
80
+ "api_key_required": true,
81
+ "rate_limit": 0
82
+ },
83
+ "mistralai": {
84
+ "id": "mistralai",
85
+ "name": "Mistral AI",
86
+ "endpoint": "https://api.mistral.ai/v1",
87
+ "type": "openai",
88
+ "api_key_required": true,
89
+ "rate_limit": 0
90
+ },
91
+ "stabilityai": {
92
+ "id": "stabilityai",
93
+ "name": "Stability AI",
94
+ "endpoint": "https://api.stability.ai/v2beta",
95
+ "type": "stabilityai",
96
+ "api_key_required": true,
97
+ "rate_limit": 0
98
+ },
99
+ "kilo": {
100
+ "id": "kilo",
101
+ "name": "KiloCode",
102
+ "endpoint": "https://kilocode.ai/api/openrouter",
103
+ "type": "openai",
104
+ "api_key_required": true,
105
+ "rate_limit": 0
106
+ },
107
+ "perplexity": {
108
+ "id": "perplexity",
109
+ "name": "Perplexity AI",
110
+ "endpoint": "https://api.perplexity.ai",
111
+ "type": "openai",
112
+ "api_key_required": true,
113
+ "rate_limit": 0
114
+ },
115
+ "poe": {
116
+ "id": "poe",
117
+ "name": "Poe",
118
+ "endpoint": "https://api.poe.com/v1",
119
+ "type": "poe",
120
+ "api_key_required": true,
121
+ "rate_limit": 0
122
+ },
123
+ "lanai": {
124
+ "id": "lanai",
125
+ "name": "Llama AI",
126
+ "endpoint": "https://api.lanai.ai/v1",
127
+ "type": "lanai",
128
+ "api_key_required": true,
129
+ "rate_limit": 0
130
+ },
131
+ "amazon": {
132
+ "id": "amazon",
133
+ "name": "Amazon Bedrock",
134
+ "endpoint": "https://api.amazon.com/bedrock/v1",
135
+ "type": "amazon",
136
+ "api_key_required": true,
137
+ "rate_limit": 0
138
+ },
139
+ "ibm": {
140
+ "id": "ibm",
141
+ "name": "IBM Watson",
142
+ "endpoint": "https://api.ibm.com/watson/v1",
143
+ "type": "ibm",
144
+ "api_key_required": true,
145
+ "rate_limit": 0
146
+ },
147
+ "microsoft": {
148
+ "id": "microsoft",
149
+ "name": "Microsoft Azure AI",
150
+ "endpoint": "https://api.microsoft.com/v1",
151
+ "type": "microsoft",
152
+ "api_key_required": true,
153
+ "rate_limit": 0
154
+ }
155
+ }
156
+ }
@@ -0,0 +1,11 @@
1
+ fastapi
2
+ uvicorn
3
+ python-multipart
4
+ pydantic
5
+ httpx
6
+ python-jose[cryptography]
7
+ passlib[bcrypt]
8
+ python-dotenv
9
+ google-genai
10
+ openai
11
+ anthropic
@@ -0,0 +1,94 @@
1
+ {
2
+ "rotations": {
3
+ "coding": {
4
+ "model_name": "coding",
5
+ "providers": [
6
+ {
7
+ "provider_id": "gemini",
8
+ "api_key": "YOUR_GEMINI_API_KEY",
9
+ "models": [
10
+ {
11
+ "name": "gemini-2.0-flash",
12
+ "weight": 3,
13
+ "rate_limit": 0
14
+ },
15
+ {
16
+ "name": "gemini-1.5-pro",
17
+ "weight": 1,
18
+ "rate_limit": 0
19
+ }
20
+ ]
21
+ },
22
+ {
23
+ "provider_id": "openai",
24
+ "api_key": "YOUR_OPENAI_API_KEY",
25
+ "models": [
26
+ {
27
+ "name": "gpt-4",
28
+ "weight": 2,
29
+ "rate_limit": 0
30
+ },
31
+ {
32
+ "name": "gpt-3.5-turbo",
33
+ "weight": 1,
34
+ "rate_limit": 0
35
+ }
36
+ ]
37
+ },
38
+ {
39
+ "provider_id": "anthropic",
40
+ "api_key": "YOUR_ANTHROPIC_API_KEY",
41
+ "models": [
42
+ {
43
+ "name": "claude-3-5-sonnet-20241022",
44
+ "weight": 2,
45
+ "rate_limit": 0
46
+ },
47
+ {
48
+ "name": "claude-3-haiku-20240307",
49
+ "weight": 1,
50
+ "rate_limit": 0
51
+ }
52
+ ]
53
+ }
54
+ ]
55
+ },
56
+ "general": {
57
+ "model_name": "general",
58
+ "providers": [
59
+ {
60
+ "provider_id": "gemini",
61
+ "api_key": "YOUR_GEMINI_API_KEY",
62
+ "models": [
63
+ {
64
+ "name": "gemini-1.5-pro",
65
+ "weight": 2,
66
+ "rate_limit": 0
67
+ },
68
+ {
69
+ "name": "gemini-2.0-flash",
70
+ "weight": 1,
71
+ "rate_limit": 0
72
+ }
73
+ ]
74
+ },
75
+ {
76
+ "provider_id": "openai",
77
+ "api_key": "YOUR_OPENAI_API_KEY",
78
+ "models": [
79
+ {
80
+ "name": "gpt-4",
81
+ "weight": 2,
82
+ "rate_limit": 0
83
+ },
84
+ {
85
+ "name": "gpt-3.5-turbo",
86
+ "weight": 1,
87
+ "rate_limit": 0
88
+ }
89
+ ]
90
+ }
91
+ ]
92
+ }
93
+ }
94
+ }
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aisbf
3
- Version: 0.1.0
3
+ Version: 0.1.1
4
4
  Summary: AISBF - AI Service Broker Framework || AI Should Be Free - A modular proxy server for managing multiple AI provider integrations
5
5
  Home-page: https://git.nexlab.net/nexlab/aisbf.git
6
6
  Author: AISBF Contributors
7
7
  Author-email: stefy@nexlab.net
8
8
  Maintainer-email: Stefy Lanza <stefy@nexlab.net>
9
- License: GPL-3.0-or-later
9
+ License-Expression: GPL-3.0-or-later
10
10
  Project-URL: Homepage, https://git.nexlab.net/nexlab/aisbf.git
11
11
  Project-URL: Repository, https://git.nexlab.net/nexlab/aisbf.git
12
12
  Project-URL: Documentation, https://git.nexlab.net/nexlab/aisbf.git
@@ -15,7 +15,6 @@ Keywords: ai,proxy,api,openai,anthropic,google,ollama,llm,chat,broker
15
15
  Classifier: Development Status :: 3 - Alpha
16
16
  Classifier: Intended Audience :: Developers
17
17
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
18
- Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
19
18
  Classifier: Programming Language :: Python :: 3
20
19
  Classifier: Programming Language :: Python :: 3.8
21
20
  Classifier: Programming Language :: Python :: 3.9
@@ -26,9 +25,21 @@ Classifier: Operating System :: OS Independent
26
25
  Requires-Python: >=3.8
27
26
  Description-Content-Type: text/markdown
28
27
  License-File: LICENSE.txt
28
+ Requires-Dist: fastapi
29
+ Requires-Dist: uvicorn
30
+ Requires-Dist: python-multipart
31
+ Requires-Dist: pydantic
32
+ Requires-Dist: httpx
33
+ Requires-Dist: python-jose[cryptography]
34
+ Requires-Dist: passlib[bcrypt]
35
+ Requires-Dist: python-dotenv
36
+ Requires-Dist: google-genai
37
+ Requires-Dist: openai
38
+ Requires-Dist: anthropic
29
39
  Dynamic: author-email
30
40
  Dynamic: home-page
31
41
  Dynamic: license-file
42
+ Dynamic: requires-dist
32
43
  Dynamic: requires-python
33
44
 
34
45
  # AISBF - AI Service Broker Framework || AI Should Be Free
@@ -0,0 +1,15 @@
1
+ aisbf/__init__.py,sha256=GbB1LZegRn_u5RHETw9iLnZUeS5_mkNYZ5s7jaL3Xp4,1971
2
+ aisbf/config.py,sha256=6n7izwrZw8CBLY9aI8dMxi8EaVVIXaWbe1mc9xsjW_g,5277
3
+ aisbf/handlers.py,sha256=Az7OVUDGLORwrfrQYqtaQ4bOPDE3NZJyYqub2DFZVfs,7479
4
+ aisbf/models.py,sha256=LT1NaQVAw0VWXL-j3hdfNlXCA9HeiET_O3GDj3t9XC4,1883
5
+ aisbf/providers.py,sha256=jQGKYqrb-1RB3s4XrKK7AbX-7W5Cl3HG7Yc_riMkcyA,11942
6
+ aisbf-0.1.1.data/data/share/aisbf/main.py,sha256=MnsDZQH-vFT4KMhlVtVK8uGyeYiRa3orka4AVH_nLIc,4550
7
+ aisbf-0.1.1.data/data/share/aisbf/providers.json,sha256=9L5GO6sQ2Z6zndGed0AckvYNV1DMr9r7tSdZ9fJxYlA,3934
8
+ aisbf-0.1.1.data/data/share/aisbf/requirements.txt,sha256=lp6cPakAO3lpTCwQ27THf-PNz_HIpzCELrtpdgo6-2o,133
9
+ aisbf-0.1.1.data/data/share/aisbf/rotations.json,sha256=SzbmMeTRR0vVTrYTMwxSPxjXLVr8zxjaI4HYRxjyExQ,2123
10
+ aisbf-0.1.1.dist-info/licenses/LICENSE.txt,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
11
+ aisbf-0.1.1.dist-info/METADATA,sha256=jgGUF13YI-sXxjRf2hgqD3cJ7G8WyLSEh2YMNyEn-jg,4190
12
+ aisbf-0.1.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
13
+ aisbf-0.1.1.dist-info/entry_points.txt,sha256=zYLNG5rYg0OM6zVQuJnxt7yKd6bf2OM9jiHy1ydPudY,36
14
+ aisbf-0.1.1.dist-info/top_level.txt,sha256=D7THOopMCIUH203TRSRdc1e_MBOC4OLJTCrMGBcn4Gc,6
15
+ aisbf-0.1.1.dist-info/RECORD,,
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ aisbf = main:main
@@ -1,10 +0,0 @@
1
- aisbf/__init__.py,sha256=GbB1LZegRn_u5RHETw9iLnZUeS5_mkNYZ5s7jaL3Xp4,1971
2
- aisbf/config.py,sha256=6n7izwrZw8CBLY9aI8dMxi8EaVVIXaWbe1mc9xsjW_g,5277
3
- aisbf/handlers.py,sha256=Az7OVUDGLORwrfrQYqtaQ4bOPDE3NZJyYqub2DFZVfs,7479
4
- aisbf/models.py,sha256=LT1NaQVAw0VWXL-j3hdfNlXCA9HeiET_O3GDj3t9XC4,1883
5
- aisbf/providers.py,sha256=jQGKYqrb-1RB3s4XrKK7AbX-7W5Cl3HG7Yc_riMkcyA,11942
6
- aisbf-0.1.0.dist-info/licenses/LICENSE.txt,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
7
- aisbf-0.1.0.dist-info/METADATA,sha256=y6_cawA4qVHCibOHbGzYoZWEV3L21qY89lJPb57G6NA,3944
8
- aisbf-0.1.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
9
- aisbf-0.1.0.dist-info/top_level.txt,sha256=D7THOopMCIUH203TRSRdc1e_MBOC4OLJTCrMGBcn4Gc,6
10
- aisbf-0.1.0.dist-info/RECORD,,
File without changes