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.1.tar.gz (66.7 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.1-py3-none-any.whl (78.6 kB view details)

Uploaded Python 3

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

Hashes for hasapi-0.1.1.tar.gz
Algorithm Hash digest
SHA256 24d92fd224f38770fabf6494dddee6e23600ecbbf90a54df30b676ac519c6ab2
MD5 6f6bfe0e7c2170a6241f64a0f8d1838e
BLAKE2b-256 9bdee9f22cd4428b549064c8fdb2340d71d3da0a901d9425935e3a5818f54e17

See more details on using hashes here.

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

Hashes for hasapi-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 67743a5ad0aedbf8d20dd9bb134dcd225155b683695f8a075e215a469fa6c870
MD5 6b4f79689237d73c53420d3b644b0f4c
BLAKE2b-256 ce2bbd52e94dc10b55825ac2ebaa8698492ddba6e796f5117e71ab1a67c1d6cc

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