esemsc-am4224 commited on
Commit
193af56
·
1 Parent(s): eaf29ed

feat: added limited retrieval-only interface

Browse files
data/agentbase-v1.1.csv CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:4b76495040cb17bea5f45a2c051c040893bfea9f624f18fc836ddb5d75c68cb3
3
- size 14146922
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:56d1626919e2042cde14d5cc26ebe9582626dab0e7b4eac0ece9a8d0acbac999
3
+ size 14130110
data/agentbase_mini.csv DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:e2db4a90cb3e226e333e780759e1f9e92b952fa105540d81afd4be3229b02705
3
- size 434433
 
 
 
 
data/embeddings/BAAI_bge-large-en-v1.5_18d58ad4370dc14d.npz CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:871437bcb334f3cd37d0863d10a98b895a24017fbc31e718f90d048fda796108
3
- size 37193182
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:153580c91d9a8f52aedc70c95f2bff83ac1d0052d68e9f53fd8a216867fad38f
3
+ size 37193486
data/embeddings/BAAI_bge-large-en-v1.5_35225dd43945b254.npz DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:dba2da69db6c7e31a1a6a11630d7c07ceb799a62d804de5494ee030099e76761
3
- size 37193033
 
 
 
 
data/embeddings/BAAI_bge-large-en-v1.5_63af9b74ada2385d.npz DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:153580c91d9a8f52aedc70c95f2bff83ac1d0052d68e9f53fd8a216867fad38f
3
- size 37193486
 
 
 
 
data/embeddings/BAAI_bge-large-en-v1.5_74e561a3a431c1aa.npz DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:76b07cf52ca92c1d4754fa5be65dbd5e61c8f169cde7d78df4017bfc2e68d08f
3
- size 37192831
 
 
 
 
data/embeddings/BAAI_bge-large-en-v1.5_8c6dc4a78211c0a6.npz CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:ed776a604d0ad19da7fcf8ccd22db8d2a89edb01529c2739d2431ed41b449335
3
- size 37191805
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a0f77ce768bd8950fded3ed3c8176fb5801ccc35258e0c0c485ef886a8ea8dd6
3
+ size 37194090
data/embeddings/BAAI_bge-large-en-v1.5_cf2365f1cf47d288.npz DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:aebdb5484fb2ded2131984ad6e88ea4c45820fea4052ced8a9b241c88beb8d1b
3
- size 37192370
 
 
 
 
requirements.txt CHANGED
@@ -3,7 +3,15 @@ pytest
3
  flake8
4
  pandas
5
  matplotlib
 
 
 
 
 
6
  torch
 
 
 
7
  streamlit
8
  SQLAlchemy
9
  sentence-transformers
@@ -16,5 +24,11 @@ Scrapy
16
  scrapy-playwright
17
  PyDispatcher
18
  langdetect
 
19
  altair<5
 
 
 
 
 
20
  standard-imghdr
 
3
  flake8
4
  pandas
5
  matplotlib
6
+ seaborn
7
+ scikit-learn
8
+ scipy
9
+ umap-learn
10
+ hdbscan
11
  torch
12
+ langchain
13
+ langchain-community
14
+ langchain-openai
15
  streamlit
16
  SQLAlchemy
17
  sentence-transformers
 
24
  scrapy-playwright
25
  PyDispatcher
26
  langdetect
27
+ rouge-score
28
  altair<5
29
+ pytrec-eval==0.5
30
+ pytrec-eval-terrier==0.5.6
31
+ mcp
32
+ langchain-mcp-adapters
33
+ langchain-anthropic
34
  standard-imghdr
interface.py → ui/interface.py RENAMED
@@ -160,8 +160,8 @@ class AgentBaseUI:
160
 
161
  if __name__ == "__main__":
162
  BASE_DIR = Path(__file__).resolve().parent
163
- agentbase_path = BASE_DIR / "data/agentbase-v1.1.csv"
164
- platforms_path = BASE_DIR / "data/platforms.csv"
165
 
166
  agentbaseui = AgentBaseUI(agentbase_path, platforms_path)
167
  agentbaseui.header_panel()
 
160
 
161
  if __name__ == "__main__":
162
  BASE_DIR = Path(__file__).resolve().parent
163
+ agentbase_path = BASE_DIR / "../data/agentbase-v1.1.csv"
164
+ platforms_path = BASE_DIR / "../data/platforms.csv"
165
 
166
  agentbaseui = AgentBaseUI(agentbase_path, platforms_path)
167
  agentbaseui.header_panel()
ui/retrieval_interface.py ADDED
@@ -0,0 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ AgentBase Retrieval UI (limited interface).
3
+
4
+ Author: Arastun Mammadli
5
+ Date: [Current Date]
6
+ """
7
+
8
+ from typing import List, Tuple
9
+ from pathlib import Path
10
+ import streamlit as st
11
+ import pandas as pd
12
+ import numpy as np
13
+ import html
14
+
15
+ from retrieval.models.bm25 import BM25Retriever
16
+ from retrieval.models.sentence_bert import DenseRetriever
17
+ from retrieval.utils import load_queries
18
+
19
+
20
+ @st.cache_resource()
21
+ def load_retrievers(agentbase_path: str, index_configs: List[str]) -> Tuple[dict, dict]:
22
+ bm25s = {}
23
+ bges = {}
24
+ for idx_config in index_configs:
25
+ bm25s[idx_config] = BM25Retriever(agentbase_path, index_config=idx_config)
26
+ bges[idx_config] = DenseRetriever("BAAI/bge-large-en-v1.5", agentbase_path, index_config=idx_config)
27
+ return bm25s, bges
28
+
29
+ @st.cache_resource()
30
+ def load_agentbase_data(agentbase_path: str) -> pd.DataFrame:
31
+ return pd.read_csv(agentbase_path)
32
+
33
+
34
+ class AgentBaseUI:
35
+ """
36
+ AgentBase Streamlit-based UI Components.
37
+ """
38
+ def __init__(self, agentbase_path, platforms_path):
39
+ self.agents_df = load_agentbase_data(agentbase_path)
40
+ self.platforms_df = pd.read_csv(platforms_path)
41
+ self.bm25s, self.bges = load_retrievers(agentbase_path, index_configs=["v1", "naive"])
42
+
43
+ # selection options and defaults
44
+ self.retrieval_models = ["bge-large-en-v1.5", "bm25"]
45
+ self.selected_model = "bge-large-en-v1.5"
46
+ self.indexing_configs = ["v1", "naive"]
47
+ self.indexing_config = "v1"
48
+
49
+ def header_panel(self):
50
+ st.set_page_config(page_title="AgentBase", layout="wide")
51
+ st.title("AgentBase Retriever")
52
+ st.write("A Large-Scale Agent Collection for Automated Agent Recommendation.")
53
+
54
+ if "query" not in st.session_state:
55
+ st.session_state.query = ""
56
+
57
+ col1, col2, col3 = st.columns([4, 1, 1])
58
+ with col1:
59
+ st.text_input("", placeholder="Type to search...", key="query")
60
+ with col2:
61
+ self.selected_model = st.selectbox("", self.retrieval_models, index=0)
62
+ with col3:
63
+ self.indexing_config = st.selectbox("", self.indexing_configs, index=0)
64
+
65
+ _, col2 = st.columns([2, 1])
66
+ with col2:
67
+ with st.expander("See explanation"):
68
+ st.write('''
69
+ - **Retrieval Models**:
70
+ - **BGE-Large**: a dense retrieval model.
71
+ - **BM25**: a sparse retrieval model.
72
+ - **Indexing Configurations**:
73
+ - **v1**: using all columns with priority ordering (e.g., name, description come first).
74
+ - **naive**: using agent name and description only.
75
+ ''')
76
+
77
+ def retrieval_panel(self):
78
+ top_k = 5
79
+ if st.session_state.query:
80
+ self.filtered_df = self.retrieve_agents(st.session_state.query, top_k)
81
+ else:
82
+ self.filtered_df = self.agents_df.copy()
83
+ self.filtered_df["scores"] = 0.0
84
+
85
+ if len(self.filtered_df) > 0:
86
+ key_columns = [
87
+ "agent_name",
88
+ "platform_name",
89
+ "agent_description",
90
+ "agent_pricing",
91
+ "base_model",
92
+ "agent_url",
93
+ "scores",
94
+ ]
95
+ if (self.filtered_df["scores"] == 0).all():
96
+ key_columns.remove("scores")
97
+
98
+ display_df = self.filtered_df[key_columns].head(top_k)
99
+ csv_text = self.filtered_df.head(top_k).to_csv(index=False)
100
+ jsonl_text = self.filtered_df.head(top_k).to_json(orient="records", lines=True)
101
+
102
+ # --- header row with actions ---
103
+ col1, col2, col3 = st.columns([4, 1, 1])
104
+ with col1:
105
+ st.write(f"Showing {top_k} of {len(self.agents_df)} agents")
106
+ with col2:
107
+ copy_button(csv_text, "Copy CSV")
108
+ with col3:
109
+ copy_button(jsonl_text, "Copy JSONL")
110
+
111
+ agent_config = {
112
+ "agent_name": st.column_config.TextColumn(
113
+ "agent_name", width="medium"
114
+ ),
115
+ "agent_url": st.column_config.LinkColumn(
116
+ "agent_url", display_text="Visit →"
117
+ ),
118
+ "agent_description": st.column_config.TextColumn(
119
+ "agent_description", width="large"
120
+ ),
121
+ "agent_accessibility": st.column_config.TextColumn(
122
+ "agent_accessibility", width="small"
123
+ ),
124
+ "agent_pricing": st.column_config.TextColumn(
125
+ "agent_pricing", width="medium"
126
+ ),
127
+ "base_model": st.column_config.TextColumn(
128
+ "base_model", width="medium"
129
+ ),
130
+ }
131
+ st.dataframe(
132
+ display_df,
133
+ column_config=agent_config,
134
+ use_container_width=True,
135
+ hide_index=True,
136
+ )
137
+ else:
138
+ st.info("No agents match your search.")
139
+
140
+ def retrieve_agents(self, query, top_k=100) -> pd.DataFrame:
141
+ """
142
+ Returns a filtered dataframe with updated scores.
143
+ Default maximum top_k of 100
144
+ """
145
+ if self.selected_model == 'bm25':
146
+ res = self.bm25s[self.indexing_config].retrieve(query, top_k)
147
+ elif self.selected_model == 'bge-large-en-v1.5':
148
+ res = self.bges[self.indexing_config].retrieve(query, top_k)
149
+ else:
150
+ raise ValueError(f"Selected model must be one of {self.retrieval_models}")
151
+
152
+ self.agents_df["scores"] = 0 # reset
153
+ agent_ids, _ = zip(*res)
154
+ filtered_df = self.agents_df.loc[self.agents_df.agent_id.isin(agent_ids)]
155
+ for index, row in filtered_df.iterrows():
156
+ score = dict(res).get(row['agent_id'], 0)
157
+ filtered_df.at[index, 'scores'] = score
158
+
159
+ return filtered_df.sort_values(by="scores", ascending=False)
160
+
161
+
162
+ def copy_button(text: str, label: str):
163
+ safe = html.escape(text)
164
+ st.components.v1.html(
165
+ f"""
166
+ <button
167
+ onclick="
168
+ navigator.clipboard.writeText(`{safe}`);
169
+ const btn = this;
170
+ const original = btn.innerText;
171
+ btn.innerText = 'Copied';
172
+ btn.classList.add('copied');
173
+ setTimeout(() => {{
174
+ btn.innerText = original;
175
+ btn.classList.remove('copied');
176
+ }}, 900);
177
+ "
178
+ style="
179
+ width:100%;
180
+ padding:10px 12px;
181
+ border-radius:8px;
182
+ border:1px solid #ddd;
183
+ cursor:pointer;
184
+ font-size:14px;
185
+ background:#fff;
186
+ transition:
187
+ background-color 0.15s ease,
188
+ transform 0.08s ease,
189
+ box-shadow 0.08s ease;
190
+ "
191
+ onmouseover="this.style.background='#f6f7f9'"
192
+ onmouseout="this.style.background='#fff'"
193
+ onmousedown="
194
+ this.style.transform='scale(0.97)';
195
+ this.style.boxShadow='inset 0 2px 6px rgba(0,0,0,0.15)';
196
+ "
197
+ onmouseup="
198
+ this.style.transform='scale(1)';
199
+ this.style.boxShadow='none';
200
+ "
201
+ >
202
+ {label}
203
+ </button>
204
+ """,
205
+ height=52,
206
+ )
207
+
208
+ if __name__ == "__main__":
209
+ BASE_DIR = Path(__file__).resolve().parent
210
+ agentbase_path = BASE_DIR / "../data/agentbase-v1.1.csv"
211
+ platforms_path = BASE_DIR / "../data/platforms.csv"
212
+
213
+ agentbaseui = AgentBaseUI(agentbase_path, platforms_path)
214
+ agentbaseui.header_panel()
215
+ agentbaseui.retrieval_panel()