File size: 3,341 Bytes
b42034d
d4d137d
 
b42034d
 
d4d137d
b42034d
 
d4d137d
 
 
b42034d
 
 
 
 
 
 
 
 
 
 
 
 
95dc0e1
b42034d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95dc0e1
 
 
b42034d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import os

import requests
from dotenv import load_dotenv

import streamlit as st

load_dotenv()
DEPLOY_URL = os.getenv("DEPLOY_API_URL")
LOCAL_URL = os.getenv("LOCAL_API_URL")
API_URL = DEPLOY_URL or LOCAL_URL


def get_docs():
    if "docs" not in st.session_state:
        with st.spinner("Fetching available docs..."):
            response = requests.get(f"{API_URL}/get_tables", timeout=10)
            response.raise_for_status()
            data = response.json()

        tables = data.get("tables")
        st.session_state.docs = tables


def render_sidebar():
    if "docs" in st.session_state:
        with st.sidebar:
            st.markdown(
                """
                <style>
                .gradient-text {
                    font-weight: bold;
                    background: -webkit-linear-gradient(left, #ff4b1f, #1fddff);
                    -webkit-background-clip: text;
                    -webkit-text-fill-color: transparent;
                    display: inline;
                    font-size: 3em;
                }
                </style>
                <div class="gradient-text">📚 PyDocs AI</div>
                """,
                unsafe_allow_html=True,
            )
            option = st.selectbox(
                label=" ",
                label_visibility="collapsed",
                placeholder="Documentation",
                index=None,
                options=st.session_state.get("docs", None),
            )

            if st.button("New Chat"):
                st.session_state.messages = []

        return option


def fetch_response(prompt, option, context):
    with requests.post(
        f"{API_URL}/query",
        timeout=50,
        json={"prompt": prompt, "doc_name": option, "context": context},
        stream=True,
    ) as response:
        response.raise_for_status()

        for chunk in response.iter_content(chunk_size=None):
            if chunk:
                text = chunk.decode("utf-8")
                yield text


def render_chat_ui(option):
    if "messages" not in st.session_state:
        with st.chat_message("assistant"):
            st.write(
                "Hello! I'am your python libraries AI assistant. Please first :blue[**select a documentation**] from the sidebar dropdown, and then ask me anything from :blue[**that documentation**]."
            )

        st.session_state.messages = []

    for message in st.session_state.messages:
        with st.chat_message(message["role"]):
            if message["role"] == "user":
                st.write(message["content"])
            else:
                st.write(message["content"])

    if prompt := st.chat_input("Ask question:"):
        if not option:
            st.error("Please select documentation")
            return

        st.session_state.messages.append({"role": "user", "content": prompt})

        with st.chat_message("user"):
            st.write(prompt)

        with st.chat_message("assistant"):
            with st.spinner("Generating response...", show_time=True):
                stream = fetch_response(prompt, option, st.session_state.messages)
                response_text = str(st.write_stream(stream, cursor="|"))

                st.session_state.messages.append(
                    {"role": "assistant", "content": response_text}
                )