cyberandy commited on
Commit
e53e16b
·
verified ·
1 Parent(s): dce4ae1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +139 -50
app.py CHANGED
@@ -1,10 +1,7 @@
1
  import gradio as gr
2
  import requests
3
- from typing import Dict, Tuple
4
- import logging
5
-
6
- logging.basicConfig(level=logging.INFO)
7
- logger = logging.getLogger(__name__)
8
 
9
  def get_features(text: str) -> Dict:
10
  """Get neural features from the API using the exact website parameters."""
@@ -24,62 +21,154 @@ def get_features(text: str) -> Dict:
24
  response.raise_for_status()
25
  return response.json()
26
  except Exception as e:
27
- logger.error(f"Error in API call: {str(e)}")
28
  return None
29
 
30
- def format_output(text: str) -> Tuple[str, str, str]:
31
- data = get_features(text)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
- if not data or 'results' not in data:
34
- return "Error analyzing text", "", ""
35
-
36
- output = "# Neural Feature Analysis\n\n"
 
 
 
 
 
 
 
 
 
 
37
 
38
- # Process each token's features
39
- for result in data['results']:
40
- token = result['token']
41
- if token == '<bos>':
42
- continue
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
 
44
- output += f"## Token: {token}\n\n"
 
 
 
 
45
 
46
- for feature in result['top_features']:
47
- feature_id = feature['feature_index']
48
- activation = feature['activation_value']
49
- feature_url = f"https://www.neuronpedia.org/gemma-2-2b/20-gemmascope-res-16k/{feature_id}"
50
 
51
- output += f"- Feature {feature_id} (Activation: {activation:.2f})\n"
52
- output += f" [View on Neuronpedia]({feature_url})\n\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
53
 
54
- # Use first non-BOS token's top feature for the dashboard
55
  dashboard_html = ""
56
- feature_label = "No features found"
57
 
58
  for result in data['results']:
59
- if result['token'] != '<bos>' and result['top_features']:
60
- top_feature = result['top_features'][0]
61
- feature_id = top_feature['feature_index']
62
- activation = top_feature['activation_value']
63
 
64
- dashboard_url = f"https://www.neuronpedia.org/gemma-2-2b/20-gemmascope-res-16k/{feature_id}?embed=true&embedexplanation=true&embedplots=true&embedtest=true&height=300"
65
- dashboard_html = f'''
66
- <div style="border:1px solid #eee;border-radius:8px;padding:1px;background:#fff;">
67
- <iframe
68
- src="{dashboard_url}"
69
- width="100%"
70
- height="600px"
71
- frameborder="0"
72
- style="border-radius:8px;"
73
- ></iframe>
 
 
 
 
 
74
  </div>
75
- '''
76
- feature_label = f"Feature {feature_id} Dashboard (Activation: {activation:.2f})"
77
- break
 
 
 
 
 
 
 
 
 
 
78
 
79
- return output, dashboard_html, feature_label
 
80
 
81
  def create_interface():
82
- with gr.Blocks() as interface:
83
  gr.Markdown("# Neural Feature Analyzer")
84
  gr.Markdown("*Analyze text using Gemma's interpretable neural features*")
85
 
@@ -98,14 +187,14 @@ def create_interface():
98
  ], inputs=input_text)
99
 
100
  with gr.Column():
101
- output_text = gr.Markdown()
102
- feature_label = gr.Text(show_label=False)
103
- dashboard = gr.HTML()
104
 
105
  analyze_btn.click(
106
- fn=lambda text: format_output(text),
107
  inputs=input_text,
108
- outputs=[output_text, dashboard, feature_label]
109
  )
110
 
111
  return interface
 
1
  import gradio as gr
2
  import requests
3
+ from typing import Dict, Tuple, List
4
+ import json
 
 
 
5
 
6
  def get_features(text: str) -> Dict:
7
  """Get neural features from the API using the exact website parameters."""
 
21
  response.raise_for_status()
22
  return response.json()
23
  except Exception as e:
 
24
  return None
25
 
26
+ def create_feature_html(feature_id: int, activation: float, selected: bool = False) -> str:
27
+ """Create HTML for an individual feature card."""
28
+ border_class = "border-blue-500 border-2" if selected else "border border-gray-200"
29
+ return f"""
30
+ <div class="feature-card mb-4 {border_class} rounded-lg shadow hover:shadow-md transition-all cursor-pointer p-4"
31
+ data-feature-id="{feature_id}" onclick="selectFeature(this, {feature_id})">
32
+ <div class="flex justify-between items-center">
33
+ <div>
34
+ <span class="font-semibold">Feature {feature_id}</span>
35
+ <span class="ml-2 text-gray-600">(Activation: {activation:.2f})</span>
36
+ </div>
37
+ </div>
38
+ </div>
39
+ """
40
+
41
+ def create_token_section(token: str, features: List[Dict], initial_count: int = 3) -> str:
42
+ """Create HTML for a token section with its features."""
43
+ features_html = "".join([
44
+ create_feature_html(f['feature_index'], f['activation_value'])
45
+ for f in features[:initial_count]
46
+ ])
47
 
48
+ show_more = ""
49
+ if len(features) > initial_count:
50
+ remaining = len(features) - initial_count
51
+ hidden_features = "".join([
52
+ create_feature_html(f['feature_index'], f['activation_value'])
53
+ for f in features[initial_count:]
54
+ ])
55
+ show_more = f"""
56
+ <div class="hidden" id="more-features-{token}">{hidden_features}</div>
57
+ <button class="text-blue-500 hover:text-blue-700 text-sm mt-2"
58
+ onclick="toggleFeatures('{token}', this)">
59
+ Show {remaining} More Features
60
+ </button>
61
+ """
62
 
63
+ return f"""
64
+ <div class="mb-6">
65
+ <h2 class="text-xl font-bold mb-4">Token: {token}</h2>
66
+ <div id="features-{token}">
67
+ {features_html}
68
+ </div>
69
+ {show_more}
70
+ </div>
71
+ """
72
+
73
+ def create_dashboard_html(feature_id: int, activation: float) -> str:
74
+ """Create HTML for the feature dashboard."""
75
+ return f"""
76
+ <div class="border border-gray-200 rounded-lg p-4">
77
+ <h3 class="text-lg font-semibold mb-4">Feature {feature_id} Dashboard (Activation: {activation:.2f})</h3>
78
+ <iframe
79
+ src="https://www.neuronpedia.org/gemma-2-2b/20-gemmascope-res-16k/{feature_id}?embed=true&embedexplanation=true&embedplots=true&embedtest=true&height=300"
80
+ width="100%"
81
+ height="600"
82
+ frameborder="0"
83
+ class="rounded-lg"
84
+ ></iframe>
85
+ </div>
86
+ """
87
+
88
+ def create_interface_html(data: Dict) -> str:
89
+ """Create the complete interface HTML."""
90
+ js_code = """
91
+ <script>
92
+ function selectFeature(element, featureId) {
93
+ // Remove selection from all features
94
+ document.querySelectorAll('.feature-card').forEach(card => {
95
+ card.classList.remove('border-blue-500', 'border-2');
96
+ card.classList.add('border', 'border-gray-200');
97
+ });
98
+
99
+ // Add selection to clicked feature
100
+ element.classList.remove('border', 'border-gray-200');
101
+ element.classList.add('border-blue-500', 'border-2');
102
 
103
+ // Update dashboard
104
+ document.getElementById('dashboard-container').innerHTML =
105
+ `<iframe src="https://www.neuronpedia.org/gemma-2-2b/20-gemmascope-res-16k/${featureId}?embed=true&embedexplanation=true&embedplots=true&embedtest=true&height=300"
106
+ width="100%" height="600" frameborder="0" class="rounded-lg"></iframe>`;
107
+ }
108
 
109
+ function toggleFeatures(token, button) {
110
+ const moreFeatures = document.getElementById(`more-features-${token}`);
111
+ const featuresContainer = document.getElementById(`features-${token}`);
 
112
 
113
+ if (moreFeatures.classList.contains('hidden')) {
114
+ moreFeatures.classList.remove('hidden');
115
+ featuresContainer.innerHTML += moreFeatures.innerHTML;
116
+ button.textContent = 'Show Less';
117
+ } else {
118
+ const allFeatures = featuresContainer.querySelectorAll('.feature-card');
119
+ for (let i = 3; i < allFeatures.length; i++) {
120
+ allFeatures[i].remove();
121
+ }
122
+ moreFeatures.classList.add('hidden');
123
+ button.textContent = `Show ${moreFeatures.querySelectorAll('.feature-card').length} More Features`;
124
+ }
125
+ }
126
+ </script>
127
+ """
128
 
129
+ tokens_html = ""
130
  dashboard_html = ""
131
+ first_feature = None
132
 
133
  for result in data['results']:
134
+ if result['token'] == '<bos>':
135
+ continue
 
 
136
 
137
+ tokens_html += create_token_section(result['token'], result['top_features'])
138
+
139
+ if not first_feature and result['top_features']:
140
+ first_feature = result['top_features'][0]
141
+ dashboard_html = create_dashboard_html(
142
+ first_feature['feature_index'],
143
+ first_feature['activation_value']
144
+ )
145
+
146
+ return f"""
147
+ <div class="p-6">
148
+ {js_code}
149
+ <div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
150
+ <div class="space-y-6">
151
+ {tokens_html}
152
  </div>
153
+ <div class="lg:sticky lg:top-6">
154
+ <div id="dashboard-container">
155
+ {dashboard_html}
156
+ </div>
157
+ </div>
158
+ </div>
159
+ </div>
160
+ """
161
+
162
+ def analyze_features(text: str) -> Tuple[str, str, str]:
163
+ data = get_features(text)
164
+ if not data:
165
+ return "Error analyzing text", "", ""
166
 
167
+ interface_html = create_interface_html(data)
168
+ return interface_html, "", ""
169
 
170
  def create_interface():
171
+ with gr.Blocks(css="") as interface:
172
  gr.Markdown("# Neural Feature Analyzer")
173
  gr.Markdown("*Analyze text using Gemma's interpretable neural features*")
174
 
 
187
  ], inputs=input_text)
188
 
189
  with gr.Column():
190
+ output_html = gr.HTML()
191
+ feature_label = gr.Text(show_label=False, visible=False)
192
+ dashboard = gr.HTML(visible=False)
193
 
194
  analyze_btn.click(
195
+ fn=analyze_features,
196
  inputs=input_text,
197
+ outputs=[output_html, feature_label, dashboard]
198
  )
199
 
200
  return interface