Skip to main content

Modern Python web framework for AI-native APIs (LLM + RAG + Streaming)

Project description

HasAPI - Modern Python Framework for AI-Native APIs & UIs

Python License Version

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 API
  • examples/simple_chatbot.py - AI chatbot
  • examples/simple_rag.py - RAG system
  • examples/full_api.py - Complete REST API with auth
  • examples/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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hasapi-0.1.0.tar.gz (66.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

hasapi-0.1.0-py3-none-any.whl (78.6 kB view details)

Uploaded Python 3

File details

Details for the file hasapi-0.1.0.tar.gz.

File metadata

  • Download URL: hasapi-0.1.0.tar.gz
  • Upload date:
  • Size: 66.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.18

File hashes

Hashes for hasapi-0.1.0.tar.gz
Algorithm Hash digest
SHA256 8bb2fe928a60a48f76f699901ba169af46096e7fda77e2b533d0c3df65278802
MD5 df347286364b559fefd6d82e25d32216
BLAKE2b-256 a81737cd5483a7763e64981a47454bcd87b20fb8c4482b2c3185eb98e2f8dc2f

See more details on using hashes here.

File details

Details for the file hasapi-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: hasapi-0.1.0-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

Hashes for hasapi-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e4a540627f14d8afc8aa27245b9d649eccb01b354be0c30eac637f769a14c57a
MD5 00cd7c5cb486c53bf0e1f43c88f1e7b9
BLAKE2b-256 55d3dc43cf1ed7e9a4426d5398a0671a951beb91b3a9b6637be7c601732310f9

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page