config.py 7.47 KB
Newer Older
1
2
import os
import chromadb
Timothy J. Baek's avatar
Timothy J. Baek committed
3
from chromadb import Settings
4
5
from secrets import token_bytes
from base64 import b64encode
6
from constants import ERROR_MESSAGES
Timothy J. Baek's avatar
Timothy J. Baek committed
7
from pathlib import Path
Timothy J. Baek's avatar
Timothy J. Baek committed
8
import json
Timothy J. Baek's avatar
Timothy J. Baek committed
9
10
import markdown
from bs4 import BeautifulSoup
Timothy J. Baek's avatar
Timothy J. Baek committed
11

Timothy J. Baek's avatar
Timothy J. Baek committed
12

lucasew's avatar
lucasew committed
13
14
try:
    from dotenv import load_dotenv, find_dotenv
15

lucasew's avatar
lucasew committed
16
17
18
    load_dotenv(find_dotenv("../.env"))
except ImportError:
    print("dotenv not installed, skipping...")
Timothy J. Baek's avatar
Timothy J. Baek committed
19

Timothy J. Baek's avatar
Timothy J. Baek committed
20
21

####################################
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
22
# ENV (dev,test,prod)
Timothy J. Baek's avatar
Timothy J. Baek committed
23
24
####################################

Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
25
ENV = os.environ.get("ENV", "dev")
Timothy J. Baek's avatar
Timothy J. Baek committed
26
27


Timothy J. Baek's avatar
Timothy J. Baek committed
28
29
30
31
32
33
34
35
try:
    with open(f"../package.json", "r") as f:
        PACKAGE_DATA = json.load(f)
except:
    PACKAGE_DATA = {"version": "0.0.0"}

VERSION = PACKAGE_DATA["version"]

Timothy J. Baek's avatar
Timothy J. Baek committed
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

# Function to parse each section
def parse_section(section):
    items = []
    for li in section.find_all("li"):
        # Extract raw HTML string
        raw_html = str(li)

        # Extract text without HTML tags
        text = li.get_text(separator=" ", strip=True)

        # Split into title and content
        parts = text.split(": ", 1)
        title = parts[0].strip() if len(parts) > 1 else ""
        content = parts[1].strip() if len(parts) > 1 else text

        items.append({"title": title, "content": content, "raw": raw_html})
    return items


try:
    with open("../CHANGELOG.md", "r") as file:
        changelog_content = file.read()
except:
    changelog_content = ""

# Convert markdown content to HTML
html_content = markdown.markdown(changelog_content)

# Parse the HTML content
soup = BeautifulSoup(html_content, "html.parser")

# Initialize JSON structure
changelog_json = {}

# Iterate over each version
for version in soup.find_all("h2"):
    version_number = version.get_text().strip().split(" - ")[0][1:-1]  # Remove brackets
    date = version.get_text().strip().split(" - ")[1]

    version_data = {"date": date}

    # Find the next sibling that is a h3 tag (section title)
    current = version.find_next_sibling()

    print(current)

    while current and current.name != "h2":
        if current.name == "h3":
            section_title = current.get_text().lower()  # e.g., "added", "fixed"
            section_items = parse_section(current.find_next_sibling("ul"))
            version_data[section_title] = section_items

        # Move to the next element
        current = current.find_next_sibling()

    changelog_json[version_number] = version_data


CHANGELOG = changelog_json

Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
97
98
99
####################################
# DATA/FRONTEND BUILD DIR
####################################
lucasew's avatar
lucasew committed
100

Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
101
DATA_DIR = str(Path(os.getenv("DATA_DIR", "./data")).resolve())
lucasew's avatar
lucasew committed
102
FRONTEND_BUILD_DIR = str(Path(os.getenv("FRONTEND_BUILD_DIR", "../build")))
Timothy J. Baek's avatar
Timothy J. Baek committed
103

Timothy J. Baek's avatar
Timothy J. Baek committed
104
105
106
107
108
109
try:
    with open(f"{DATA_DIR}/config.json", "r") as f:
        CONFIG_DATA = json.load(f)
except:
    CONFIG_DATA = {}

110
####################################
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
111
# File Upload DIR
112
113
####################################

Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
114
115
UPLOAD_DIR = f"{DATA_DIR}/uploads"
Path(UPLOAD_DIR).mkdir(parents=True, exist_ok=True)
Timothy J. Baek's avatar
Timothy J. Baek committed
116

Timothy J. Baek's avatar
Timothy J. Baek committed
117
118
119
120
121
122
123
124

####################################
# Cache DIR
####################################

CACHE_DIR = f"{DATA_DIR}/cache"
Path(CACHE_DIR).mkdir(parents=True, exist_ok=True)

125
126
127
128
129
130
131

####################################
# Docs DIR
####################################

DOCS_DIR = f"{DATA_DIR}/docs"
Path(DOCS_DIR).mkdir(parents=True, exist_ok=True)
Timothy J. Baek's avatar
Timothy J. Baek committed
132

133
134
135
136
####################################
# OLLAMA_API_BASE_URL
####################################

137
138
139
OLLAMA_API_BASE_URL = os.environ.get(
    "OLLAMA_API_BASE_URL", "http://localhost:11434/api"
)
Timothy J. Baek's avatar
Timothy J. Baek committed
140
141
142
143

if ENV == "prod":
    if OLLAMA_API_BASE_URL == "/ollama/api":
        OLLAMA_API_BASE_URL = "http://host.docker.internal:11434/api"
144

Timothy J. Baek's avatar
Timothy J. Baek committed
145
146
147
148
149
####################################
# OPENAI_API
####################################

OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY", "")
150
151
152
153
OPENAI_API_BASE_URL = os.environ.get("OPENAI_API_BASE_URL", "")

if OPENAI_API_BASE_URL == "":
    OPENAI_API_BASE_URL = "https://api.openai.com/v1"
Timothy J. Baek's avatar
Timothy J. Baek committed
154

155
156
157
158
159

####################################
# WEBUI
####################################

Kyle McLaren's avatar
Kyle McLaren committed
160
ENABLE_SIGNUP = os.environ.get("ENABLE_SIGNUP", True)
161
DEFAULT_MODELS = os.environ.get("DEFAULT_MODELS", None)
Timothy J. Baek's avatar
Timothy J. Baek committed
162
163
164
165


DEFAULT_PROMPT_SUGGESTIONS = (
    CONFIG_DATA["ui"]["prompt_suggestions"]
Timothy J. Baek's avatar
Timothy J. Baek committed
166
167
168
    if "ui" in CONFIG_DATA
    and "prompt_suggestions" in CONFIG_DATA["ui"]
    and type(CONFIG_DATA["ui"]["prompt_suggestions"]) is list
Timothy J. Baek's avatar
Timothy J. Baek committed
169
    else [
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
        {
            "title": ["Help me study", "vocabulary for a college entrance exam"],
            "content": "Help me study vocabulary: write a sentence for me to fill in the blank, and I'll try to pick the correct option.",
        },
        {
            "title": ["Give me ideas", "for what to do with my kids' art"],
            "content": "What are 5 creative things I could do with my kids' art? I don't want to throw them away, but it's also so much clutter.",
        },
        {
            "title": ["Tell me a fun fact", "about the Roman Empire"],
            "content": "Tell me a random fun fact about the Roman Empire",
        },
        {
            "title": ["Show me a code snippet", "of a website's sticky header"],
            "content": "Show me a code snippet of a website's sticky header in CSS and JavaScript.",
        },
Timothy J. Baek's avatar
Timothy J. Baek committed
186
    ]
187
)
Timothy J. Baek's avatar
Timothy J. Baek committed
188
189


Timothy J. Baek's avatar
Timothy J. Baek committed
190
191
192
DEFAULT_USER_ROLE = "pending"
USER_PERMISSIONS = {"chat": {"deletion": True}}

193

194
####################################
195
# WEBUI_VERSION
196
197
####################################

Timothy J. Baek's avatar
Timothy J. Baek committed
198
WEBUI_VERSION = os.environ.get("WEBUI_VERSION", "v1.0.0-alpha.100")
199
200

####################################
201
# WEBUI_AUTH (Required for security)
202
203
####################################

204
WEBUI_AUTH = True
205

Timothy J. Baek's avatar
Timothy J. Baek committed
206
####################################
207
# WEBUI_SECRET_KEY
Timothy J. Baek's avatar
Timothy J. Baek committed
208
209
####################################

210
211
WEBUI_SECRET_KEY = os.environ.get(
    "WEBUI_SECRET_KEY",
Timothy J. Baek's avatar
Timothy J. Baek committed
212
213
214
    os.environ.get(
        "WEBUI_JWT_SECRET_KEY", "t0p-s3cr3t"
    ),  # DEPRECATED: remove at next major version
215
)
216

217
if WEBUI_AUTH and WEBUI_SECRET_KEY == "":
Timothy J. Baek's avatar
Timothy J. Baek committed
218
    raise ValueError(ERROR_MESSAGES.ENV_VAR_NOT_FOUND)
219
220
221
222
223

####################################
# RAG
####################################

224
CHROMA_DATA_PATH = f"{DATA_DIR}/vector_db"
225
# this uses the model defined in the Dockerfile ENV variable. If you dont use docker or docker based deployments such as k8s, the default embedding model will be used (all-MiniLM-L6-v2)
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
226
RAG_EMBEDDING_MODEL = os.environ.get("RAG_EMBEDDING_MODEL", "all-MiniLM-L6-v2")
227
# device type ebbeding models - "cpu" (default), "cuda" (nvidia gpu required) or "mps" (apple silicon) - choosing this right can lead to better performance
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
228
229
230
RAG_EMBEDDING_MODEL_DEVICE_TYPE = os.environ.get(
    "RAG_EMBEDDING_MODEL_DEVICE_TYPE", "cpu"
)
Timothy J. Baek's avatar
Timothy J. Baek committed
231
CHROMA_CLIENT = chromadb.PersistentClient(
Timothy J. Baek's avatar
Timothy J. Baek committed
232
233
    path=CHROMA_DATA_PATH,
    settings=Settings(allow_reset=True, anonymized_telemetry=False),
Timothy J. Baek's avatar
Timothy J. Baek committed
234
)
235
236
CHUNK_SIZE = 1500
CHUNK_OVERLAP = 100
Timothy J. Baek's avatar
Timothy J. Baek committed
237

Timothy J. Baek's avatar
Timothy J. Baek committed
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252

RAG_TEMPLATE = """Use the following context as your learned knowledge, inside <context></context> XML tags.
<context>
    [context]
</context>

When answer to user:
- If you don't know, just say that you don't know.
- If you don't know when you are not sure, ask for clarification.
Avoid mentioning that you obtained the information from the context.
And answer according to the language of the user's question.
        
Given the context information, answer the query.
Query: [query]"""

Timothy J. Baek's avatar
Timothy J. Baek committed
253
254
255
####################################
# Transcribe
####################################
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
256
257
258

WHISPER_MODEL = os.getenv("WHISPER_MODEL", "base")
WHISPER_MODEL_DIR = os.getenv("WHISPER_MODEL_DIR", f"{CACHE_DIR}/whisper/models")
Timothy J. Baek's avatar
Timothy J. Baek committed
259
260
261
262
263
264
265


####################################
# Images
####################################

AUTOMATIC1111_BASE_URL = os.getenv("AUTOMATIC1111_BASE_URL", "")