File size: 13,946 Bytes
ccbdc5a
2e88125
d14c18c
db45716
fd7ea58
 
5af8fe2
ccbdc5a
8f81c46
be73b82
8f81c46
fd7ea58
2e88125
fd7ea58
d14c18c
 
fd7ea58
bebef8d
fd7ea58
d14c18c
ccbdc5a
d14c18c
658485c
2e88125
b3b0363
 
e0b606d
b3b0363
b61c416
b3b0363
 
 
22c3cc6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b3b0363
e0b606d
 
 
 
 
b3b0363
 
 
24eaafe
 
b3b0363
24eaafe
f7d1d03
24eaafe
 
f7d1d03
b3b0363
 
 
 
 
 
 
 
 
 
fd7ea58
 
803bb00
fd7ea58
 
 
 
 
 
 
 
 
 
 
 
f7d1d03
fd7ea58
 
f7d1d03
fd7ea58
 
 
 
 
 
 
 
 
 
 
 
f7d1d03
 
 
fd7ea58
 
 
 
 
 
 
 
ccbdc5a
 
fd7ea58
 
 
 
 
 
22c3cc6
fd7ea58
b3b0363
 
f7d1d03
 
fd7ea58
 
 
 
e0b606d
 
 
 
fd7ea58
 
 
 
64b1911
fd7ea58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b708f46
fd7ea58
 
e0b606d
fd7ea58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
803bb00
 
 
 
fd7ea58
 
 
 
 
 
 
c7a05e5
 
 
 
 
 
 
 
 
 
 
 
fd7ea58
c7a05e5
e20c3d5
 
fd7ea58
e20c3d5
7cbee86
 
c7a05e5
fd7ea58
c7a05e5
fd7ea58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
803bb00
 
 
 
fd7ea58
 
 
 
803bb00
fd7ea58
 
 
 
 
 
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
import streamlit as st
import requests
import os
from gliner import GLiNER
from streamlit_autorefresh import st_autorefresh
import time
import ast
tok = os.getenv("TOK")



#st_autorefresh(interval=10000, key="volter")

st.write(tok)
def Target_Identification(userinput):
    model = GLiNER.from_pretrained("Ihor/gliner-biomed-bi-small-v1.0")
    labels = ["Protein","Mutation"]
    entities = model.predict_entities(userinput, labels, threshold=0.5)

    for entity in entities:
        if entity["label"] == "Protein":
            return entity["text"]




appuser=st.user

def APP():

    def sidebarview():
        '''experimental sidebar'''


        # Get projects with error handling and caching
        @st.cache_data(ttl=20)  # Cache for 5 minutes to reduce API calls
        def scan_for_project_availability_cached(user_id):
                    try:
                        request_url = f"https://thexforce-combat-backend.hf.space/{user_id}/projects"
                        response = requests.get(
                                request_url,
                                headers={
                                    "Content-Type": "application/json",
                                    "Authorization": f"Bearer {tok}",
                                },
                                timeout=10  # Add timeout to prevent hanging
                            )
                            
                        if response.status_code == 200:
                                response_json = response.json()
                                pros = response_json.get("projects", [])  # Default to empty list if no projects key
                                
                                project_list = []
                                if pros:  # Check if pros is not None or empty
                                    for pro in pros:
                                        if isinstance(pro, dict):
                                            project_name = pro.get("project")
                                            if project_name:  # Only add if project name exists
                                                project_list.append(project_name)
                                        else:
                                            if pro:  # Only add if pro is not None or empty
                                                project_list.append(str(pro))
                                
                                return project_list
                        else:
                                st.error(f"Failed to fetch projects. Status code: {response.status_code}")
                                return []
                                
                    except requests.exceptions.RequestException as e:
                                st.error(f"Error fetching projects: {str(e)}")
                                return []
                    except Exception as e:
                                st.error(f"Unexpected error: {str(e)}")
                                return []

        
        with st.sidebar:  
            
            
            
            projects = scan_for_project_availability_cached(appuser.get("email"))
            projectname = None

            if len(projects) > 0:
                agree = st.checkbox("create a new project ?")
                if agree:
                            #projectname = st.selectbox("Select Project", projects)
                    projectname = st.text_input("Enter project name:")
                    st.session_state.projectname=projectname
                else:
                    projectname = st.selectbox("Select Project", projects)
                    st.session_state.projectname=projectname
                            
            else:
                projectname = st.text_input("Enter project name:")

                st.session_state.projectname = projectname
                '''experimental sidebar'''

    sidebarview()
    
    
    tab_map = {
        0: "BIO ENGINEERING LAB @newMATTER",
        1:"BIO ENGINEERING LAB 2  @newMATTER"
    }

    tab_selection = st.pills(
        "TABS",
        options=tab_map.keys(),
        format_func=lambda option: tab_map[option],
        selection_mode="single",
    )

    def SHOWTABS():
        if tab_selection == 0:
            # Two-column split
            #left_col, right_col = st.columns([0.3, 0.7],vertical_alignment="center",border=True)

            # CSS to make right column sticky
                st.markdown("""
                <style>
                [data-testid="column"]:nth-of-type(2) {
                    position: sticky;
                    top: 0;
                    align-self: flex-start;
                    height: 100vh;
                    overflow-y: auto;
                    background-color: #0E1117;
                    padding: 10px;
                    border-left: 1px solid rgba(255,255,255,0.1);
                }
                </style>
                """, unsafe_allow_html=True)
                '''
                with left_col:
                option_map = {
                    0: "@OriginAI  Nanobody Engineering:",
                }
                selection = st.pills(
                    "BIOLOGICS",
                    options=option_map.keys(),
                    format_func=lambda option: option_map[option],
                    selection_mode="single",
                )

                if selection == 0:
                    st.markdown(
                        "<p style='color:white;background-color:orange;font-weight:bold'> Nanobody [CANCER targeted]</p>",
                        unsafe_allow_html=True,
                    )

                    

      
                    
                with right_col:
                '''
                bio_input = st.chat_input(" Ready for Action ! ")

                # FIXED: Removed caching and added force_refresh parameter
                def fetch_ops(force_refresh=False):



                    
                    # Clear cache if force_refresh is True
                    if force_refresh and 'ops_cache' in st.session_state:
                        del st.session_state.ops_cache

                    fetch_url=f"https://thexforce-combat-backend.hf.space/{appuser.get('email')}/{st.session_state.projectname}/individual/experiment"
                    
                    response = requests.get(
                        fetch_url,
                        headers={
                            "Content-Type": "application/json",
                            "Authorization": f"Bearer {tok}",
                        },
                    )
                    return response.json()

                if "messages" not in st.session_state:
                    st.session_state.messages = []

                if len(st.session_state.messages) > 0:
                    for msg in st.session_state.messages:
                        with st.chat_message(msg["role"]):
                            st.markdown(msg["content"])

                if bio_input:
                    st.session_state.messages.append({"role": "user", "content": bio_input})
                    with st.chat_message("user"):
                        st.markdown(bio_input)

                    if st.session_state.projectname in [None, ""]:
                        st.markdown(":orange-badge[⚠️ Set Projectname]")
                    else:
                        identified_target = Target_Identification(bio_input)
                        #st.warning(f"TARGET IDENTIFIED IS : {identified_target}")

                        payload = {
                            "uid": appuser.get("email"),
                            "pid": st.session_state.projectname,
                            "target": identified_target or None,
                            "high_level_bio_query": bio_input,
                        }

                        response = requests.post(
                            "https://thexforce-combat-backend.hf.space/application_layer_agent",
                            json=payload,
                            headers={
                                "Content-Type": "application/json",
                                "Authorization":f"Bearer {tok}",
                            },
                        )

                        plan_response = response.json()

                        with st.chat_message("assistant"):
                            st.markdown(plan_response)

                        # FIXED: Use animations while waiting for backend processing
                        with st.spinner("🧬 Processing biological data..."):
                            # Try multiple times with short delays between attempts
                            fetch_ops_response = None
                            max_attempts = 6
                            
                            for attempt in range(max_attempts):
                                fetch_ops_response = fetch_ops(force_refresh=True)
                                
                                # Check if we got data
                                if fetch_ops_response and fetch_ops_response.get("exp"):
                                    break
                                
                                # Short delay before next attempt (non-blocking)
                                if attempt < max_attempts - 1:  # Don't sleep on last attempt
                                    import time
                                    time.sleep(0.5)  # Much shorter sleep between retries
                        
                        # Show completion animation
                        #if fetch_ops_response and fetch_ops_response.get("exp"):
                            #st.write("")
                        #else:
                            #st.info("⏳ Operations are still being processed...")
                        
                        # FIXED: Better error handling with animations
                        if fetch_ops_response:
                            #st.write("Debug - Full response:", fetch_ops_response)  # Debug line - remove in production
                            
                            exp_data = fetch_ops_response.get("exp")
                            if exp_data is not None and len(exp_data) > 0:
                               
                                    try:
                                        exp_list = ast.literal_eval(exp_data) if isinstance(exp_data, str) else exp_data
                                        st.session_state.exp_list = exp_list
                                    except Exception as e:
                                        st.error(f"Failed to parse experimental data: {e}")
                                        st.session_state.exp_list = []

                                    #-----------------------------
                                    #RENDER UI FOR PILLS
                                    # -----------------------------
                                    #This part must be OUTSIDE `st.chat_message`
                                
                                    if "exp_list" in st.session_state and st.session_state.exp_list:

                                        tabs = st.tabs([item["operation"] for item in st.session_state.exp_list])
                                        
                                        for i, tab in enumerate(tabs):
                                            with tab:
                                                st.write(st.session_state.exp_list[i]["output"])
                                

                                
                            else:
                                # Animated waiting message
                                st.info("🔄 No experimental data found yet. Operations may still be processing...")
                                with st.container():
                                    st.markdown("""
                                        <div style="text-align: center;">
                                            <div class="spinner"></div>
                                        </div>
                                        <style>
                                        .spinner {
                                            border: 4px solid #f3f3f3;
                                            border-top: 4px solid #ff6b35;
                                            border-radius: 50%;
                                            width: 30px;
                                            height: 30px;
                                            animation: spin 1s linear infinite;
                                            margin: 10px auto;
                                        }
                                        @keyframes spin {
                                            0% { transform: rotate(0deg); }
                                            100% { transform: rotate(360deg); }
                                        }
                                        </style>
                                    """, unsafe_allow_html=True)
                        else:
                            st.error("❌ Failed to fetch operations data")
                            st.markdown("🔄 **Tip:** Try refreshing or submitting your query again.")

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


        elif tab_selection == 1:
            st.markdown("coming soon")

    if st.user.is_logged_in:
        if st.button("🚪 Logout"):
            st.logout()
            st.rerun()
        #st.markdown(f"## {st.user.email}")
        SHOWTABS()
    else:
        st.info("Please log in to access the Bio Lab")
        if st.button("Log in"):
            st.login("auth0")
            st.stop()