8. Maeser Example (with Flask & User Management)#

This guide demonstrates how to run Maeser as a web-based chatbot with user authentication (via GitHub OAuth or LDAP) using the official example script at example/flask_example_user_mangement.py. You’ll inspect the script, configure authentication, launch the server, and customize the application for your own RAG workflows.


8.1. Prerequisites#

  • Maeser development environment set up (see development_setup.md).

  • Python 3.10+ virtual environment activated.

  • Maeser installed in editable mode (pip install -e . or make setup).

  • Pre-built FAISS vectorstores at the paths referenced in your config.


8.2. Configuring config.yaml#

Copy the example and update the following fields:

# Path where chat logs and memory DBs are stored
LOG_SOURCE_PATH: "path/to/chat_logs"
# Your OpenAI API key for LLM access\ OPENAI_API_KEY: "your-openai-key"
# SQLite file path to store registered users and quotas
USERS_DB_PATH: "path/to/users.db"
# Directory containing FAISS vectorstore folders
VEC_STORE_PATH: "path/to/vectorstores"
# Path for chat history JSON or DB
CHAT_HISTORY_PATH: "path/to/chat_history"
# LLM model name (e.g., gpt-3.5-turbo)
LLM_MODEL_NAME: "gpt-3.5-turbo"
# Maximum requests per user and rate-limit interval (seconds)
MAX_REQUESTS: 100
RATE_LIMIT_INTERVAL: 60

# GitHub OAuth Configuration
GITHUB_CLIENT_ID: "your-client-id"
GITHUB_CLIENT_SECRET: "your-client-secret"
GITHUB_AUTH_CALLBACK_URI: "http://hostIP:3002/login/github_callback"
GITHUB_TIMEOUT: 10

# LDAP3 Authenticator Settings
LDAP3_NAME: "ldap"
LDAP_SERVER_URLS:
  - "ldap://ldap.example.com"
LDAP_BASE_DN: "dc=example,dc=com"
LDAP_ATTRIBUTE_NAME: "uid"
LDAP_SEARCH_FILTER: "(objectClass=person)"
LDAP_OBJECT_CLASS: "person"
LDAP_ATTRIBUTES:
  - "cn"
  - "mail"
LDAP_CA_CERT_PATH: "/path/to/ca_cert.pem"
LDAP_CONNECTION_TIMEOUT: 5

Field Descriptions:

  • LOG_SOURCE_PATH: Directory/file prefix for RAG memory databases.

  • OPENAI_API_KEY: Key to authenticate with OpenAI’s API.

  • USERS_DB_PATH: SQLite DB for storing user records and quotas.

  • VEC_STORE_PATH: Base path where FAISS indexes are saved.

  • CHAT_HISTORY_PATH: Path to persist chat logs via ChatLogsManager.

  • LLM_MODEL_NAME: Which OpenAI or LLM model to invoke.

  • MAX_REQUESTS / RATE_LIMIT_INTERVAL: Controls per-user rate limiting.

  • GITHUB_ entries: Configure GitHub OAuth flow.

  • LDAP3_ entries: Configure LDAP authentication parameters.


8.3. 1. Inspect flask_example_user_mangement.py#

8.3.1. 1.1 Configuration Imports & Env Setup#

Imports all config variables and sets the OpenAI API key in the environment.

from config_example import (
    LOG_SOURCE_PATH, OPENAI_API_KEY, USERS_DB_PATH,
    VEC_STORE_PATH, MAX_REQUESTS, RATE_LIMIT_INTERVAL,
    GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET,
    GITHUB_AUTH_CALLBACK_URI, GITHUB_TIMEOUT,
    CHAT_HISTORY_PATH,
    LDAP3_NAME, LDAP_SERVER_URLS, LDAP_BASE_DN,
    LDAP_ATTRIBUTE_NAME, LDAP_SEARCH_FILTER,
    LDAP_OBJECT_CLASS, LDAP_ATTRIBUTES,
    LDAP_CA_CERT_PATH, LDAP_CONNECTION_TIMEOUT,
    LLM_MODEL_NAME
)
import os
os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY

8.3.2. 1.2 Chat Logs & Session Manager Setup#

Initializes chat logging and session management to track conversations and user queries.

from maeser.chat.chat_logs import ChatLogsManager
from maeser.chat.chat_session_manager import ChatSessionManager

# Persist chat history
chat_logs_manager = ChatLogsManager(CHAT_HISTORY_PATH)
# Manage multiple chat sessions
sessions_manager = ChatSessionManager(chat_logs_manager=chat_logs_manager)

8.3.3. 1.3 Prompt Definitions#

Defines system prompts that inject persona and context into the LLM.

maeser_prompt = (
    """You are speaking from the perspective of Karl G. Maeser.\n"
    "You will answer questions about your life history based on provided context.\n"
    "{context}"""
)

byu_prompt = (
    """You are a BYU historian.\n"
    "You will answer questions about Brigham Young University’s history based on provided context.\n"
    "{context}"""
)

pipeline_prompt = (
    """You are Karl G. Maeser or a BYU historian.\n"
    "You will answer history questions based on provided context.\n"
    "{context}"""
)

8.3.4. 1.4 RAG Graph Construction#

Creates three RAG pipelines (Karl Maeser, BYU, and combined pipeline) and registers them as named branches.

from maeser.graphs.simple_rag import get_simple_rag
from maeser.graphs.pipeline_rag import get_pipeline_rag
from langgraph.graph.graph import CompiledGraph

# Simple RAG for Karl G. Maeser
maeser_graph: CompiledGraph = get_simple_rag(
    vectorstore_path=f"{VEC_STORE_PATH}/maeser",
    vectorstore_index="index",
    memory_filepath=f"{LOG_SOURCE_PATH}/maeser.db",
    system_prompt_text=maeser_prompt,
    model=LLM_MODEL_NAME
)
sessions_manager.register_branch(
    branch_name="maeser",
    branch_label="Karl G. Maeser History",
    graph=maeser_graph
)

# Simple RAG for BYU History
byu_graph: CompiledGraph = get_simple_rag(
    vectorstore_path=f"{VEC_STORE_PATH}/byu",
    vectorstore_index="index",
    memory_filepath=f"{LOG_SOURCE_PATH}/byu.db",
    system_prompt_text=byu_prompt,
    model=LLM_MODEL_NAME
)
sessions_manager.register_branch(
    branch_name="byu",
    branch_label="BYU History",
    graph=byu_graph
)

# Pipeline across both domains
pipeline_graph: CompiledGraph = get_pipeline_rag(
    vectorstore_config={
        "byu history": f"{VEC_STORE_PATH}/byu",
        "karl g maeser": f"{VEC_STORE_PATH}/maeser"
    },
    memory_filepath=f"{LOG_SOURCE_PATH}/pipeline_memory.db",
    api_key=OPENAI_API_KEY,
    system_prompt_text=pipeline_prompt,
    model=LLM_MODEL_NAME
)
sessions_manager.register_branch(
    branch_name="pipeline",
    branch_label="Pipeline",
    graph=pipeline_graph
)

8.4. 2. User Management Setup#

8.4.1. 2.1 Configure Authenticators#

Defines GitHub and LDAP authenticators for user login and request quotas.

from maeser.user_manager import UserManager, GithubAuthenticator, LDAPAuthenticator

# GitHub OAuth setup
github_authenticator = GithubAuthenticator(
    client_id=GITHUB_CLIENT_ID,
    client_secret=GITHUB_CLIENT_SECRET,
    auth_callback_uri=GITHUB_AUTH_CALLBACK_URI,
    timeout=GITHUB_TIMEOUT,
    max_requests=MAX_REQUESTS
)

# LDAP Authenticator setup
ldap3_authenticator = LDAPAuthenticator(
    name=LDAP3_NAME,
    ldap_server_urls=LDAP_SERVER_URLS,
    ldap_base_dn=LDAP_BASE_DN,
    attribute_name=LDAP_ATTRIBUTE_NAME,
    search_filter=LDAP_SEARCH_FILTER,
    object_class=LDAP_OBJECT_CLASS,
    attributes=LDAP_ATTRIBUTES,
    ca_cert_path=LDAP_CA_CERT_PATH,
    connection_timeout=LDAP_CONNECTION_TIMEOUT
)

8.4.2. 2.2 Initialize User Manager#

Creates a UserManager instance and registers the authenticators.

# Initialize user management with request limits
user_manager = UserManager(
    db_file_path=USERS_DB_PATH,
    max_requests=MAX_REQUESTS,
    rate_limit_interval=RATE_LIMIT_INTERVAL
)
# Register both authenticators
user_manager.register_authenticator(name="github", authenticator=github_authenticator)
user_manager.register_authenticator(name=LDAP3_NAME, authenticator=ldap3_authenticator)

8.5. 3. Flask Application Setup#

Initializes the Flask app with both chat session and user managers, then registers all routes via blueprints.

from flask import Flask
from maeser.blueprints import App_Manager

base_app = Flask(__name__)
app_manager = App_Manager(
    app=base_app,
    app_name="Maeser Auth Chat",
    flask_secret_key="secret",
    chat_session_manager=sessions_manager,
    user_manager=user_manager,
    chat_head="/static/Karl_G_Maeser.png"
)
# Mount routes and return the full app
app = app_manager.add_flask_blueprint()

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=3002, debug=True)

8.6. 4. Run the Application#

Activate your virtual environment and execute:

python example/flask_example_user_mangement.py

Navigate to http://localhost:3002, authenticate via GitHub or LDAP, select a branch, and start chatting.


8.7. 5. Register Your GitHub OAuth App#

  1. In GitHub, go to Settings → Developer Settings → OAuth Apps → New OAuth App.

  2. Set Homepage URL to http://localhost:3002 and Authorization callback URL to http://localhost:3002/login/github_callback.

  3. Copy the Client ID and Client Secret into config.yaml.


8.8. 6. LDAP Authentication (Optional)#

Ensure your LDAP server is reachable, and the fields in config.yaml match your directory’s schema. The LDAPAuthenticator will bind and lookup users based on these settings.


8.9. 7. Customization & Debugging#

  • Prompts & Branches: Modify prompt strings or register additional graphs via sessions_manager.register_branch().

  • Templates: Edit Jinja2 templates in maeser/controllers/common/templates/ for UI changes.

  • Static Assets: Override CSS/JS in common/static/.

  • Debug Mode: debug=True enables auto-reload and detailed tracebacks.

  • Production: Run with a WSGI server such as Gunicorn:

    gunicorn example.flask_example_user_mangement:app -b 0.0.0.0:3002
    

8.10. Next Steps#

  • Review the CLI example (example/terminal_example.py) for a terminal interface.

  • Dive into advanced workflows in graphs.md.

  • Study Maeser’s architecture in architecture.md before contributing.

Enjoy your authenticated Maeser chatbot! 🚀