A comprehensive open-source toolkit for AI-powered analysis and interpretation of SEC EDGAR filings, providing valuable insights for investors, fintech developers, and researchers.
from __future__ import annotations

import streamlit as st
import streamlit_pills as stp  # type: ignore # noqa: PGH003

from dev_utils.debug_dashboard.streamlit_utils import DemoOption, st_hide_page_element

# Setup page
st.set_page_config(
    page_title="sec-ai: Advanced AI for SEC EDGAR Filings",
    page_icon="🏦",
)
st_hide_page_element(tag_name="div", key="class", value="stDeployButton")
st_hide_page_element(tag_name="div", key="data-testid", value="stDecoration")
st_hide_page_element(tag_name="span", key="id", value="MainMenu")

# Add page elements

st.markdown(
    (
        "# sec-ai &nbsp;&nbsp;"
        '<a href="https://github.com/alphanome-ai/sec-ai">'
        '<img src="https://img.shields.io/github/stars/'
        'alphanome-ai/sec-ai.svg?style=social&label=Star us on GitHub!" '
        'alt="GitHub stars"></a>'
    ),
    unsafe_allow_html=True,
)


st.write(
    "A comprehensive open-source toolkit for AI-powered analysis and interpretation of "
    "SEC EDGAR filings, providing valuable insights for investors, fintech developers, "
    "and researchers.",
)


demo_options = {
    "MDNA_SUMMARIZATION": DemoOption("🧬", "MD&A Summarization"),
}
selected_demo = DemoOption.get_by_name(
    demo_options,
    stp.pills(
        "Select a demo:",
        options=DemoOption.get_names(demo_options),
        icons=DemoOption.get_icons(demo_options),
    ),
)
left, right = st.columns(2)
if selected_demo == demo_options["MDNA_SUMMARIZATION"]:
    with left, st.expander("**SEC EDGAR** INPUT", expanded=True):
        st.write("lefft")
    with right, st.expander("**SEC-AI** OUTPUT", expanded=True):
        st.write("right")

dev_utils/debug_dashboard/app.py
alphanome-ai/sec-ai
from __future__ import annotations

import os
from dataclasses import dataclass
from enum import Enum

import streamlit as st


class Environment(Enum):
    DEV = "dev"
    CI_CD = "ci_cd"
    PROD = "prod"

    @property
    def is_dev(self) -> bool:
        return self == Environment.DEV

    @property
    def is_prod(self) -> bool:
        return self == Environment.PROD

    @property
    def is_ci_cd(self) -> bool:
        return self == Environment.CI_CD


@dataclass
class Config:
    environment: Environment
    # You can obtain a free API key at https://sec-api.io
    secapio_api_key: str | None


@st.cache_data
def get_config() -> Config:
    return Config(
        environment=Environment(os.environ.get("ENVIRONMENT", Environment.DEV)),
        secapio_api_key=os.environ.get("SECAPIO_API_KEY"),
    )

dev_utils/debug_dashboard/config.py
alphanome-ai/sec-ai
from __future__ import annotations

import sec_parser as sp
import streamlit as st

from dev_utils.debug_dashboard.config import get_config


class SecDataRetriever:
    def __init__(self, secapio_api_key: str) -> None:
        self._secapio_api_key = secapio_api_key or get_config().secapio_api_key
        if not self._secapio_api_key:
            msg = (
                "SEC API key is not set. Please set it as the "
                "environment variable SECAPIO_API_KEY."
            )
            raise ValueError(msg)

    @st.cache_data(
        experimental_allow_widgets=True,
        show_spinner="Retrieving SEC EDGAR document...",
    )
    def get_metadata(
        # The prefix _ is used to circumvent a known issue with Streamlit's cache.
        # More details can be found at: https://github.com/streamlit/streamlit/issues/6109
        _self,  # noqa: N805
        *,
        doc: sp.DocumentType | str,
        url: str | None = None,
        latest_from_ticker: str | None = None,
    ) -> dict:
        self = _self  # to avoid false positives from python linters

        retriever = sp.SecapioDataRetriever(api_key=self._secapio_api_key)
        return retriever.retrieve_report_metadata(
            doc,
            url=url,
            latest_from_ticker=latest_from_ticker,
        )

    @st.cache_data(
        experimental_allow_widgets=True,
        show_spinner="Retrieving SEC EDGAR document...",
    )
    def download_html(
        # The prefix _ is used to circumvent a known issue with Streamlit's cache.
        # More details can be found at: https://github.com/streamlit/streamlit/issues/6109
        _self,  # noqa: N805
        *,
        doc: sp.DocumentType | str,
        url: str,
        sections: list[sp.SectionType | str] | None = None,
    ) -> str:
        self = _self  # to avoid false positives from python linters

        retriever = sp.SecapioDataRetriever(api_key=self._secapio_api_key)
        return retriever.get_report_html(doc, url, sections=sections)

    @st.cache_resource
    def get_semantic_elements(
        # The prefix _ is used to circumvent a known issue with Streamlit's cache.
        # More details can be found at: https://github.com/streamlit/streamlit/issues/6109
        _self,  # noqa: N805
        *,
        html: str,
    ) -> list[sp.AbstractSemanticElement]:
        parser = sp.SecParser()
        return parser.parse(html)

dev_utils/debug_dashboard/sec_data_retrieval.py
alphanome-ai/sec-ai
from __future__ import annotations

import streamlit as st


def st_hide_page_element(*, tag_name: str, key: str, value: str) -> None:
    st.markdown(
        f"""
        <style>
            {tag_name}[{key}="{value}"] {{
                visibility: hidden;
                height: 0%;
                position: fixed;
            }}
        </style>
        """,
        unsafe_allow_html=True,
    )


class DemoOption:
    @classmethod
    def get_names(cls, demo_options: dict[str, DemoOption]) -> list[str]:
        return [demo.name for demo in demo_options.values()]

    @classmethod
    def get_icons(cls, demo_options: dict[str, DemoOption]) -> list[str]:
        return [demo.icon for demo in demo_options.values()]

    @classmethod
    def get_by_name(
        cls,
        demo_options: dict[str, DemoOption],
        name: str | None,
    ) -> DemoOption:
        if name is None:
            msg = "Name cannot be None."
            raise ValueError(msg)
        return next(v for _, v in demo_options.items() if v.name == name)

    def __init__(self, icon: str, name: str) -> None:
        self.icon = icon
        self.name = name

dev_utils/debug_dashboard/streamlit_utils.py
alphanome-ai/sec-ai
# Configuration file for the Sphinx documentation builder.
#
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html

# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
import shutil
import subprocess
from pathlib import Path

project = "sec-ai"
copyright = "2023, Alphanome.AI"
author = "Alphanome.AI"


def get_git_tag() -> str:
    git_path = shutil.which("git")
    if git_path is None:
        print("git is not installed or not in the system's PATH.")
        return "unknown"

    try:
        return (
            subprocess.check_output([git_path, "describe", "--tags"])  # noqa: S603
            .strip()
            .decode("utf-8")
        )
    except Exception as e:
        print(f"An error occurred while getting the git tag: {e}")
        return "unknown"


release = get_git_tag()

# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration

extensions = [
    "myst_parser",
    "sphinx.ext.duration",
    "sphinx.ext.autosectionlabel",
    "sphinx.ext.autodoc",
    "sphinx.ext.napoleon",
    "autoapi.extension",
    "nbsphinx",
]
autoapi_type = "python"
autoapi_dirs = [f"{Path(__file__).parents[2]}/sec_ai"]

templates_path = ["_templates"]
exclude_patterns = []

# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output

html_theme = "sphinx_rtd_theme"
html_static_path = ["_static"]

docs/source/conf.py
alphanome-ai/sec-ai
from sec_ai.hello import hello


def test_hello():
    assert hello() == "Hello, world!"

tests/unit/test_hello.py
alphanome-ai/sec-ai