Modern Python web framework for AI-native APIs (LLM + RAG + Streaming)
Project description
HasAPI - Modern Python Framework for AI-Native APIs & UIs
HasAPI is a modern Python web framework designed for building AI-native APIs and interactive UIs. It combines the power of FastAPI-style APIs with Gradio-like UI components, plus native support for LLMs, RAG systems, embeddings, and templates.
🎯 Why HasAPI?
- 🚀 Fast - Up to 2.92x faster than FastAPI in real-world scenarios
- 🤖 AI-Native - Built-in LLM, RAG, and embeddings support
- 🎨 UI Components - Gradio-like interface components for rapid prototyping
- 📄 Template Engine - File-based HTML templates with Python f-string syntax
- 🔌 Pluggable - Modular architecture with swappable backends
- 💾 Database-Ready - Abstract storage layers for easy SQLite/PostgreSQL integration
- 📦 Lightweight - Install only what you need
📦 Installation
# Core framework only
pip install hasapi
# With AI support (LLM, RAG, Embeddings)
pip install hasapi[ai]
# With all features
pip install hasapi[all]
🏁 Quick Start
Minimal API
from hasapi import HasAPI, JSONResponse
app = HasAPI(title="My API", version="1.0.0")
@app.get("/")
async def root(request):
return JSONResponse({"message": "Hello from HasAPI!"})
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
AI Chatbot
import os
from hasapi import HasAPI, JSONResponse
from hasapi.ai import LLM, ConversationManager
llm = LLM(provider="openai", api_key=os.getenv("OPENAI_API_KEY"))
conversation_manager = ConversationManager()
app = HasAPI(title="AI Chatbot")
@app.post("/chat/{conversation_id}")
async def chat(request, conversation_id: str):
body = await request.json()
message = body.get("message", "")
conversation = conversation_manager.get_or_create_conversation(conversation_id)
conversation.add_message("user", message)
messages = [{"role": "system", "content": "You are a helpful AI assistant."}]
messages.extend(conversation.get_context())
result = await llm.chat(messages, temperature=0.7)
conversation.add_message("assistant", result["content"])
return JSONResponse({"response": result["content"]})
RAG System
import os
from hasapi import HasAPI, JSONResponse
from hasapi.ai import LLM, RAG, Embeddings
from hasapi.ai.vectors import InMemoryVectorStore
llm = LLM("openai", api_key=os.getenv("OPENAI_API_KEY"))
embeddings = Embeddings("openai", api_key=os.getenv("OPENAI_API_KEY"))
vector_store = InMemoryVectorStore(dimension=embeddings.get_dimension())
rag = RAG(embeddings=embeddings, llm=llm, vector_store=vector_store)
app = HasAPI(title="RAG Knowledge Base")
@app.post("/documents")
async def upload_document(request):
body = await request.json()
doc_ids = await rag.add_texts([body.get("text", "")])
return JSONResponse({"id": doc_ids[0]})
@app.post("/chat")
async def rag_chat(request):
body = await request.json()
result = await rag.answer(body.get("message", ""), top_k=3)
return JSONResponse({"answer": result["answer"], "sources": result["sources"]})
🎨 UI Components
from hasapi import HasAPI
from hasapi.ui import UI, Textbox, Text
from hasapi.templates import default_layout, TemplateResponse
def analyze_sentiment(text):
positive = ["good", "great", "awesome", "love", "happy"]
negative = ["bad", "terrible", "hate", "sad", "awful"]
text_lower = text.lower()
pos = sum(1 for w in positive if w in text_lower)
neg = sum(1 for w in negative if w in text_lower)
if pos > neg: return "😊 Positive"
elif neg > pos: return "😢 Negative"
return "😐 Neutral"
app = HasAPI(title="Sentiment Analysis")
sentiment_ui = UI(
fn=analyze_sentiment,
inputs=Textbox(label="Enter text"),
outputs=Text(label="Sentiment"),
title="📝 Sentiment Analysis"
)
@app.get("/")
async def sentiment_page(request):
layout = default_layout(sentiment_ui.title)
return TemplateResponse(
template_string=layout.wrap(sentiment_ui._render_template()),
title=sentiment_ui.title,
custom_js=sentiment_ui._get_javascript()
)
sentiment_ui._setup_api_endpoint(app)
🤖 AI Features
LLM Support
from hasapi.ai import LLM
llm = LLM("openai", api_key="sk-...")
# or: LLM("claude", api_key="sk-ant-...")
# or: LLM("openai", api_key="...", base_url="https://api.groq.com/v1")
response = await llm.chat([
{"role": "system", "content": "You are helpful"},
{"role": "user", "content": "Hello!"}
])
RAG
from hasapi.ai import RAG, Embeddings, LLM
rag = RAG(
embeddings=Embeddings("openai", api_key="..."),
llm=LLM("openai", api_key="...")
)
await rag.add_texts(["Document 1", "Document 2"])
result = await rag.answer("What is in the documents?")
🔧 Middleware
from hasapi.middleware import CORSMiddleware, JWTAuthMiddleware
app.middleware(CORSMiddleware(allow_origins=["*"]))
app.middleware(JWTAuthMiddleware(secret_key="your-secret"))
📚 Examples
examples/minimal_api.py- Basic REST APIexamples/simple_chatbot.py- AI chatbotexamples/simple_rag.py- RAG systemexamples/full_api.py- Complete REST API with authexamples/simple_demo.py- UI components demo
🔗 API Documentation
HasAPI automatically generates OpenAPI/Swagger docs at /docs.
📄 License
MIT License - See LICENSE
Built with ❤️ for the AI developer community
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hasapi-0.1.1.tar.gz.
File metadata
- Download URL: hasapi-0.1.1.tar.gz
- Upload date:
- Size: 66.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.18
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
24d92fd224f38770fabf6494dddee6e23600ecbbf90a54df30b676ac519c6ab2
|
|
| MD5 |
6f6bfe0e7c2170a6241f64a0f8d1838e
|
|
| BLAKE2b-256 |
9bdee9f22cd4428b549064c8fdb2340d71d3da0a901d9425935e3a5818f54e17
|
File details
Details for the file hasapi-0.1.1-py3-none-any.whl.
File metadata
- Download URL: hasapi-0.1.1-py3-none-any.whl
- Upload date:
- Size: 78.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.18
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
67743a5ad0aedbf8d20dd9bb134dcd225155b683695f8a075e215a469fa6c870
|
|
| MD5 |
6b4f79689237d73c53420d3b644b0f4c
|
|
| BLAKE2b-256 |
ce2bbd52e94dc10b55825ac2ebaa8698492ddba6e796f5117e71ab1a67c1d6cc
|