functions.py 7.28 KB
Newer Older
1
from pydantic import BaseModel, ConfigDict
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
2
3
4
from typing import List, Union, Optional
import time
import logging
5
6
7
8

from sqlalchemy import Column, String, Text, BigInteger, Boolean
from sqlalchemy.orm import Session

9
from apps.webui.internal.db import JSONField, Base, get_session
Timothy J. Baek's avatar
Timothy J. Baek committed
10
from apps.webui.models.users import Users
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
11
12

import json
13
14
import copy

Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
15
16
17
18
19
20
21
22
23
24
25

from config import SRC_LOG_LEVELS

log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["MODELS"])

####################
# Functions DB Schema
####################


26
27
class Function(Base):
    __tablename__ = "function"
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
28

29
30
31
32
33
34
35
36
37
38
    id = Column(String, primary_key=True)
    user_id = Column(String)
    name = Column(Text)
    type = Column(Text)
    content = Column(Text)
    meta = Column(JSONField)
    valves = Column(JSONField)
    is_active = Column(Boolean)
    updated_at = Column(BigInteger)
    created_at = Column(BigInteger)
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
39
40
41
42


class FunctionMeta(BaseModel):
    description: Optional[str] = None
43
    manifest: Optional[dict] = {}
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
44
45
46
47
48
49
50
51
52


class FunctionModel(BaseModel):
    id: str
    user_id: str
    name: str
    type: str
    content: str
    meta: FunctionMeta
53
    is_active: bool = False
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
54
55
56
    updated_at: int  # timestamp in epoch
    created_at: int  # timestamp in epoch

57
58
    model_config = ConfigDict(from_attributes=True)

Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
59
60
61
62
63
64
65
66
67

####################
# Forms
####################


class FunctionResponse(BaseModel):
    id: str
    user_id: str
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
68
    type: str
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
69
70
    name: str
    meta: FunctionMeta
Timothy J. Baek's avatar
Timothy J. Baek committed
71
    is_active: bool
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
72
73
74
75
76
77
78
79
80
81
82
    updated_at: int  # timestamp in epoch
    created_at: int  # timestamp in epoch


class FunctionForm(BaseModel):
    id: str
    name: str
    content: str
    meta: FunctionMeta


Timothy J. Baek's avatar
Timothy J. Baek committed
83
84
85
86
class FunctionValves(BaseModel):
    valves: Optional[dict] = None


Timothy J. Baek's avatar
Timothy J. Baek committed
87
class FunctionsTable:
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
88
89

    def insert_new_function(
90
        self, user_id: str, type: str, form_data: FunctionForm
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
91
92
93
94
95
    ) -> Optional[FunctionModel]:
        function = FunctionModel(
            **{
                **form_data.model_dump(),
                "user_id": user_id,
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
96
                "type": type,
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
97
98
99
100
101
102
                "updated_at": int(time.time()),
                "created_at": int(time.time()),
            }
        )

        try:
103
104
105
106
107
108
109
110
111
            with get_session() as db:
                result = Function(**function.model_dump())
                db.add(result)
                db.commit()
                db.refresh(result)
                if result:
                    return FunctionModel.model_validate(result)
                else:
                    return None
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
112
113
114
115
        except Exception as e:
            print(f"Error creating tool: {e}")
            return None

116
    def get_function_by_id(self, id: str) -> Optional[FunctionModel]:
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
117
        try:
118
119
120
            with get_session() as db:
                function = db.get(Function, id)
                return FunctionModel.model_validate(function)
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
121
122
123
        except:
            return None

124
125
    def get_functions(self, active_only=False) -> List[FunctionModel]:
        if active_only:
126
127
128
129
130
            with get_session() as db:
                return [
                    FunctionModel.model_validate(function)
                    for function in db.query(Function).filter_by(is_active=True).all()
                ]
131
        else:
132
133
134
135
136
            with get_session() as db:
                return [
                    FunctionModel.model_validate(function)
                    for function in db.query(Function).all()
                ]
137
138
139
140
141

    def get_functions_by_type(
        self, type: str, active_only=False
    ) -> List[FunctionModel]:
        if active_only:
142
143
144
145
146
147
148
            with get_session() as db:
                return [
                    FunctionModel.model_validate(function)
                    for function in db.query(Function).filter_by(
                        type=type, is_active=True
                    ).all()
                ]
149
        else:
150
151
152
153
154
            with get_session() as db:
                return [
                    FunctionModel.model_validate(function)
                    for function in db.query(Function).filter_by(type=type).all()
                ]
155

Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
156
    def get_function_valves_by_id(self, id: str) -> Optional[dict]:
157
        try:
158
159
160
            with get_session() as db:
                function = db.get(Function, id)
                return function.valves if function.valves else {}
161
162
163
164
165
166
167
168
        except Exception as e:
            print(f"An error occurred: {e}")
            return None

    def update_function_valves_by_id(
        self, id: str, valves: dict
    ) -> Optional[FunctionValves]:
        try:
169
170
171
172
173
174
            with get_session() as db:
                db.query(Function).filter_by(id=id).update(
                    {"valves": valves, "updated_at": int(time.time())}
                )
                db.commit()
                return self.get_function_by_id(id)
175
176
        except:
            return None
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
177

Timothy J. Baek's avatar
Timothy J. Baek committed
178
179
180
181
182
    def get_user_valves_by_id_and_user_id(
        self, id: str, user_id: str
    ) -> Optional[dict]:
        try:
            user = Users.get_user_by_id(user_id)
183
            user_settings = user.settings.model_dump()
Timothy J. Baek's avatar
Timothy J. Baek committed
184
185

            # Check if user has "functions" and "valves" settings
186
187
188
189
            if "functions" not in user_settings:
                user_settings["functions"] = {}
            if "valves" not in user_settings["functions"]:
                user_settings["functions"]["valves"] = {}
Timothy J. Baek's avatar
Timothy J. Baek committed
190

191
            return user_settings["functions"]["valves"].get(id, {})
Timothy J. Baek's avatar
Timothy J. Baek committed
192
193
194
195
196
197
198
199
200
        except Exception as e:
            print(f"An error occurred: {e}")
            return None

    def update_user_valves_by_id_and_user_id(
        self, id: str, user_id: str, valves: dict
    ) -> Optional[dict]:
        try:
            user = Users.get_user_by_id(user_id)
201
            user_settings = user.settings.model_dump()
Timothy J. Baek's avatar
Timothy J. Baek committed
202
203

            # Check if user has "functions" and "valves" settings
204
205
206
207
            if "functions" not in user_settings:
                user_settings["functions"] = {}
            if "valves" not in user_settings["functions"]:
                user_settings["functions"]["valves"] = {}
Timothy J. Baek's avatar
Timothy J. Baek committed
208

209
            user_settings["functions"]["valves"][id] = valves
Timothy J. Baek's avatar
Timothy J. Baek committed
210
211

            # Update the user settings in the database
212
            query = Users.update_user_by_id(user_id, {"settings": user_settings})
Timothy J. Baek's avatar
Timothy J. Baek committed
213
214
            query.execute()

215
            return user_settings["functions"]["valves"][id]
Timothy J. Baek's avatar
Timothy J. Baek committed
216
217
218
219
        except Exception as e:
            print(f"An error occurred: {e}")
            return None

Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
220
221
    def update_function_by_id(self, id: str, updated: dict) -> Optional[FunctionModel]:
        try:
222
223
224
225
226
227
228
            with get_session() as db:
                db.query(Function).filter_by(id=id).update({
                    **updated,
                    "updated_at": int(time.time()),
                })
                db.commit()
                return self.get_function_by_id(id)
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
229
230
231
        except:
            return None

Timothy J. Baek's avatar
Timothy J. Baek committed
232
233
    def deactivate_all_functions(self) -> Optional[bool]:
        try:
234
235
236
237
238
239
            with get_session() as db:
                db.query(Function).update({
                    "is_active": False,
                    "updated_at": int(time.time()),
                })
                db.commit()
Timothy J. Baek's avatar
Timothy J. Baek committed
240
241
242
243
            return True
        except:
            return None

244
    def delete_function_by_id(self, id: str) -> bool:
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
245
        try:
246
247
            with get_session() as db:
                db.query(Function).filter_by(id=id).delete()
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
248
249
250
251
252
            return True
        except:
            return False


253
Functions = FunctionsTable()