IPF commited on
Commit
f55443d
·
verified ·
1 Parent(s): 7bad154

Upload 4 files

Browse files
Files changed (3) hide show
  1. .gitattributes +1 -0
  2. app.py +28 -280
  3. or-logo1.png +3 -0
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ or-logo1.png filter=lfs diff=lfs merge=lfs -text
app.py CHANGED
@@ -175,19 +175,19 @@ class SimpleBrowser:
175
  def get_citation_index(self, cursor: int) -> int:
176
  if cursor not in self.used_citations:
177
  self.used_citations.append(cursor)
178
- return self.used_citations.index(cursor) + 1 # Start from 1 instead of 0
179
 
180
  def get_page_info(self, cursor: int) -> Optional[Dict[str, str]]:
181
  # Prioritize link_map as it stores search result metadata
182
  if cursor in self.link_map:
183
  return self.link_map[cursor]
184
-
185
  # Fallback to page_stack for opened pages
186
  if 0 <= cursor < len(self.page_stack):
187
  url = self.page_stack[cursor]
188
  page = self.pages.get(url)
189
  if page:
190
- return {'url': url, 'title': page.get('title', ''), 'snippet': ''}
191
  return None
192
 
193
  def _format_line_numbers(self, text: str, offset: int = 0) -> str:
@@ -213,9 +213,8 @@ class SimpleBrowser:
213
  except:
214
  domain = ''
215
 
216
- # Store snippet information as well
217
- self.link_map[i] = {'url': url, 'title': title, 'snippet': snippet}
218
- link_map[i] = {'url': url, 'title': title, 'snippet': snippet}
219
  link_text = f"【{i}†{title}†{domain}】" if domain else f"【{i}†{title}】"
220
  lines.append(f"{link_text}")
221
  lines.append(f" {snippet}")
@@ -486,59 +485,24 @@ def is_final_answer(text: str) -> bool:
486
  # HTML Rendering Helpers (From app_local.py)
487
  # ============================================================
488
  def render_citations(text: str, browser: SimpleBrowser) -> str:
489
- """Convert citation markers to clickable HTML links with tooltips."""
490
- # Store citation HTML to protect from markdown conversion
491
- citation_store = {}
492
- citation_counter = [0]
493
-
494
  def replace_citation(m):
495
  cursor_str = m.group(1)
496
- full_match = m.group(0) # Get the full match to extract line info
497
-
498
- # Extract line information from the citation marker
499
- # Format: 【{cursor}†L{line_start}(-L{line_end})?】
500
- line_info = ""
501
- line_match = re.search(r'†(L\d+(?:-L\d+)?)', full_match)
502
- if line_match:
503
- line_info = line_match.group(1)
504
 
505
  try:
506
  cursor = int(cursor_str)
507
  index = browser.get_citation_index(cursor)
508
-
509
  # Check if we have URL info
510
  info = browser.get_page_info(cursor)
511
  if info and info.get('url'):
512
- url = info.get('url', '')
513
- title = info.get('title', 'No Title')
514
- snippet = info.get('snippet', '')
515
-
516
- # Unescape HTML entities and remove newlines to prevent rendering issues
517
- title_display = html.unescape(title).replace('\n', ' ').replace('\r', '').strip()
518
- snippet_display = html.unescape(snippet).replace('\n', ' ').replace('\r', '').strip() if snippet else 'No description available'
519
-
520
- # Extract domain from URL
521
- try:
522
- domain = url.split('/')[2] if len(url.split('/')) > 2 else url
523
- except:
524
- domain = url
525
-
526
- # Add line info if available
527
- line_html = ""
528
- if line_info:
529
- line_html = f'<div class="citation-tooltip-line">📍 {line_info}</div>'
530
-
531
- # Create citation with tooltip (single line to avoid markdown conversion issues)
532
- tooltip_html = f'<span class="citation-tooltip"><div class="citation-tooltip-title">{title_display}</div>{line_html}<div class="citation-tooltip-snippet">{snippet_display}</div><div class="citation-tooltip-url">🔗 {html.escape(domain)}</div></span>'
533
-
534
- citation_html = f'<span class="citation-wrapper"><a href="{html.escape(url)}" target="_blank" class="citation-link">[{index}]</a>{tooltip_html}</span>'
535
-
536
- # Store citation HTML and return placeholder
537
- placeholder = f'___CITATION_{citation_counter[0]}___'
538
- citation_store[placeholder] = citation_html
539
- citation_counter[0] += 1
540
- return placeholder
541
-
542
  # Fallback if no URL
543
  return f'<span class="citation-link">[{index}]</span>'
544
  except Exception as e:
@@ -546,14 +510,19 @@ def render_citations(text: str, browser: SimpleBrowser) -> str:
546
  pass
547
  return m.group(0)
548
 
549
- # First pass: replace citations with placeholders
550
  result = re.sub(r'[【\[](\d+)†.*?[】\]]', replace_citation, text)
 
 
 
 
 
 
 
 
 
551
 
552
- # Second pass: Remove standalone URLs that appear after text (common pattern)
553
- # This removes URLs that directly follow sentences without proper citation
554
- result = re.sub(r'(?<=[.!?])\s+(https?://[^\s]+)', '', result)
555
-
556
- # Third pass: Convert basic markdown to HTML
557
  result = re.sub(r'\*\*(.+?)\*\*', r'<strong>\1</strong>', result)
558
  result = re.sub(r'\*(.+?)\*', r'<em>\1</em>', result)
559
  result = re.sub(r'`(.+?)`', r'<code>\1</code>', result)
@@ -561,17 +530,6 @@ def render_citations(text: str, browser: SimpleBrowser) -> str:
561
  if not result.startswith('<p>'):
562
  result = f'<p>{result}</p>'
563
 
564
- # Fourth pass: Restore citation HTML from placeholders
565
- for placeholder, citation_html in citation_store.items():
566
- result = result.replace(placeholder, citation_html)
567
-
568
- # Fifth pass: Deduplicate adjacent identical citations
569
- while True:
570
- new_result = re.sub(r'(<span class="citation-wrapper">.*?</span>)(\s*)\1', r'\1', result)
571
- if new_result == result:
572
- break
573
- result = new_result
574
-
575
  return result
576
 
577
  def render_thinking_streaming(text: str) -> str:
@@ -698,12 +656,8 @@ def render_tool_result(result: str, fn_name: str) -> str:
698
  <div style="color: #6b7280; font-size: 0.85rem; line-height: 1.5; margin-top: 0.75rem;">
699
  {html.escape(summary)}
700
  </div>
701
- <div style="display: flex; align-items: center; gap: 0.25rem; color: #9ca3af; font-size: 0.7rem; margin-top: 0.5rem;">
702
- <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
703
- <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path>
704
- <path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path>
705
- </svg>
706
- <span style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;">{html.escape(url.split('/')[2] if len(url.split('/')) > 2 else url)}</span>
707
  </div>
708
  </div>
709
  </div>
@@ -1525,125 +1479,7 @@ def create_interface():
1525
  .answer-section a:hover {
1526
  text-decoration: underline;
1527
  }
1528
-
1529
- /* Citation Tooltip - 小便签弹窗 */
1530
- .citation-wrapper {
1531
- position: relative;
1532
- display: inline-block;
1533
- }
1534
-
1535
- .citation-link {
1536
- color: #10a37f;
1537
- text-decoration: none;
1538
- font-weight: 600;
1539
- padding: 2px 4px;
1540
- border-radius: 4px;
1541
- background: #e6f7f1;
1542
- transition: all 0.2s ease;
1543
- cursor: pointer;
1544
- border: 1px solid #10a37f30;
1545
- }
1546
-
1547
- .citation-link:hover {
1548
- background: #10a37f;
1549
- color: white;
1550
- text-decoration: none;
1551
- }
1552
-
1553
- .citation-tooltip {
1554
- visibility: hidden;
1555
- opacity: 0;
1556
- position: absolute;
1557
- bottom: 125%;
1558
- left: 50%;
1559
- transform: translateX(-50%);
1560
- z-index: 999999;
1561
- width: 280px;
1562
- background: linear-gradient(135deg, #ffffff 0%, #f9fafb 100%);
1563
- border: 2px solid #10a37f;
1564
- border-radius: 12px;
1565
- padding: 12px 14px;
1566
- box-shadow: 0 8px 24px rgba(16, 163, 127, 0.25), 0 4px 8px rgba(0, 0, 0, 0.1);
1567
- transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
1568
- pointer-events: auto;
1569
- }
1570
-
1571
- .citation-tooltip::after {
1572
- content: "";
1573
- position: absolute;
1574
- top: 100%;
1575
- left: 50%;
1576
- transform: translateX(-50%);
1577
- border: 8px solid transparent;
1578
- border-top-color: #10a37f;
1579
- }
1580
-
1581
- /* Create an invisible bridge between link and tooltip */
1582
- .citation-tooltip::before {
1583
- content: "";
1584
- position: absolute;
1585
- top: 100%;
1586
- left: 0;
1587
- right: 0;
1588
- height: 20px;
1589
- background: transparent;
1590
- }
1591
-
1592
- .citation-wrapper:hover .citation-tooltip,
1593
- .citation-tooltip:hover {
1594
- visibility: visible;
1595
- opacity: 1;
1596
- bottom: 130%;
1597
- }
1598
-
1599
- .citation-tooltip-title {
1600
- font-weight: 600;
1601
- color: #1e293b;
1602
- font-size: 0.9rem;
1603
- margin-bottom: 8px;
1604
- line-height: 1.4;
1605
- border-bottom: 1px solid #e5e7eb;
1606
- padding-bottom: 6px;
1607
- }
1608
-
1609
- .citation-tooltip-line {
1610
- color: #059669;
1611
- font-size: 0.75rem;
1612
- font-weight: 600;
1613
- margin-bottom: 6px;
1614
- padding: 3px 8px;
1615
- background: #ecfdf5;
1616
- border-radius: 4px;
1617
- display: inline-block;
1618
- border: 1px solid #10a37f30;
1619
- }
1620
-
1621
- .citation-tooltip-snippet {
1622
- color: #475569;
1623
- font-size: 0.8rem;
1624
- line-height: 1.5;
1625
- margin-bottom: 8px;
1626
- max-height: 80px;
1627
- overflow-y: auto;
1628
- }
1629
-
1630
- .citation-tooltip-url {
1631
- color: #6b7280;
1632
- font-size: 0.7rem;
1633
- font-family: 'SF Mono', Monaco, monospace;
1634
- word-break: break-all;
1635
- padding: 2px 0;
1636
- border-top: 1px solid #e5e7eb;
1637
- padding-top: 6px;
1638
- text-decoration: none;
1639
- opacity: 0.8;
1640
- }
1641
-
1642
- .citation-tooltip-url:hover {
1643
- color: #10a37f;
1644
- opacity: 1;
1645
- }
1646
-
1647
  /* User Message Bubble - 淡蓝色背景,右对齐 */
1648
  .user-message-bubble {
1649
  background: linear-gradient(135deg, #e0f2fe 0%, #bae6fd 100%);
@@ -2230,50 +2066,6 @@ def create_interface():
2230
  color: #f0f9ff !important;
2231
  }
2232
 
2233
- /* Citation Tooltip 深色模式 */
2234
- .citation-link {
2235
- background: #064e3b !important;
2236
- border-color: #10a37f80 !important;
2237
- color: #6ee7b7 !important;
2238
- }
2239
-
2240
- .citation-link:hover {
2241
- background: #10a37f !important;
2242
- color: #ffffff !important;
2243
- }
2244
-
2245
- .citation-tooltip {
2246
- background: linear-gradient(135deg, #1f2937 0%, #111827 100%) !important;
2247
- border-color: #10a37f !important;
2248
- box-shadow: 0 8px 24px rgba(16, 163, 127, 0.4), 0 4px 8px rgba(0, 0, 0, 0.3) !important;
2249
- }
2250
-
2251
- .citation-tooltip-title {
2252
- color: #e5e7eb !important;
2253
- border-bottom-color: #374151 !important;
2254
- }
2255
-
2256
- .citation-tooltip-line {
2257
- color: #6ee7b7 !important;
2258
- background: #064e3b !important;
2259
- border-color: #10a37f50 !important;
2260
- }
2261
-
2262
- .citation-tooltip-snippet {
2263
- color: #d1d5db !important;
2264
- }
2265
-
2266
- .citation-tooltip-url {
2267
- color: #9ca3af !important;
2268
- border-top-color: #374151 !important;
2269
- opacity: 0.8 !important;
2270
- }
2271
-
2272
- .citation-tooltip-url:hover {
2273
- color: #10a37f !important;
2274
- opacity: 1 !important;
2275
- }
2276
-
2277
  /* 用户问题气泡深色模式 */
2278
  .user-message-bubble {
2279
  background: linear-gradient(135deg, #1e3a5f 0%, #1e40af 100%) !important;
@@ -2406,50 +2198,6 @@ def create_interface():
2406
  color: #e0f2fe !important;
2407
  }
2408
 
2409
- /* Citation Tooltip Gradio dark 模式 */
2410
- .dark .citation-link {
2411
- background: #064e3b !important;
2412
- border-color: #10a37f80 !important;
2413
- color: #6ee7b7 !important;
2414
- }
2415
-
2416
- .dark .citation-link:hover {
2417
- background: #10a37f !important;
2418
- color: #ffffff !important;
2419
- }
2420
-
2421
- .dark .citation-tooltip {
2422
- background: linear-gradient(135deg, #1f2937 0%, #111827 100%) !important;
2423
- border-color: #10a37f !important;
2424
- box-shadow: 0 8px 24px rgba(16, 163, 127, 0.4), 0 4px 8px rgba(0, 0, 0, 0.3) !important;
2425
- }
2426
-
2427
- .dark .citation-tooltip-title {
2428
- color: #e5e7eb !important;
2429
- border-bottom-color: #374151 !important;
2430
- }
2431
-
2432
- .dark .citation-tooltip-line {
2433
- color: #6ee7b7 !important;
2434
- background: #064e3b !important;
2435
- border-color: #10a37f50 !important;
2436
- }
2437
-
2438
- .dark .citation-tooltip-snippet {
2439
- color: #d1d5db !important;
2440
- }
2441
-
2442
- .dark .citation-tooltip-url {
2443
- color: #9ca3af !important;
2444
- border-top-color: #374151 !important;
2445
- opacity: 0.8 !important;
2446
- }
2447
-
2448
- .dark .citation-tooltip-url:hover {
2449
- color: #10a37f !important;
2450
- opacity: 1 !important;
2451
- }
2452
-
2453
  .dark .search-result-card {
2454
  background: #1f2937 !important;
2455
  border-color: #374151 !important;
 
175
  def get_citation_index(self, cursor: int) -> int:
176
  if cursor not in self.used_citations:
177
  self.used_citations.append(cursor)
178
+ return self.used_citations.index(cursor)
179
 
180
  def get_page_info(self, cursor: int) -> Optional[Dict[str, str]]:
181
  # Prioritize link_map as it stores search result metadata
182
  if cursor in self.link_map:
183
  return self.link_map[cursor]
184
+
185
  # Fallback to page_stack for opened pages
186
  if 0 <= cursor < len(self.page_stack):
187
  url = self.page_stack[cursor]
188
  page = self.pages.get(url)
189
  if page:
190
+ return {'url': url, 'title': page.get('title', '')}
191
  return None
192
 
193
  def _format_line_numbers(self, text: str, offset: int = 0) -> str:
 
213
  except:
214
  domain = ''
215
 
216
+ self.link_map[i] = {'url': url, 'title': title}
217
+ link_map[i] = {'url': url, 'title': title}
 
218
  link_text = f"【{i}†{title}†{domain}】" if domain else f"【{i}†{title}】"
219
  lines.append(f"{link_text}")
220
  lines.append(f" {snippet}")
 
485
  # HTML Rendering Helpers (From app_local.py)
486
  # ============================================================
487
  def render_citations(text: str, browser: SimpleBrowser) -> str:
488
+ """Convert citation markers to clickable HTML links."""
 
 
 
 
489
  def replace_citation(m):
490
  cursor_str = m.group(1)
491
+ # l1 = m.group(2)
492
+ # l2 = m.group(3)
 
 
 
 
 
 
493
 
494
  try:
495
  cursor = int(cursor_str)
496
  index = browser.get_citation_index(cursor)
497
+
498
  # Check if we have URL info
499
  info = browser.get_page_info(cursor)
500
  if info and info.get('url'):
501
+ # Return clickable index link pointing to reference section
502
+ # Aligned with generate_html_example.py style (green via CSS class)
503
+ url = info.get('url')
504
+ return f'<a href="{html.escape(url)}" target="_blank" class="citation-link">[{index}]</a>'
505
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
506
  # Fallback if no URL
507
  return f'<span class="citation-link">[{index}]</span>'
508
  except Exception as e:
 
510
  pass
511
  return m.group(0)
512
 
513
+ # First pass: replace citations with linked citations
514
  result = re.sub(r'[【\[](\d+)†.*?[】\]]', replace_citation, text)
515
+
516
+ # Second pass: Deduplicate adjacent identical citations
517
+ # Matches: <a ...>[N]</a> followed by optional whitespace and same link
518
+ # We repeat this until no more changes to handle multiple duplicates
519
+ while True:
520
+ new_result = re.sub(r'(<a [^>]+>\[\d+\]</a>)(\s*)\1', r'\1', result)
521
+ if new_result == result:
522
+ break
523
+ result = new_result
524
 
525
+ # Convert basic markdown to HTML
 
 
 
 
526
  result = re.sub(r'\*\*(.+?)\*\*', r'<strong>\1</strong>', result)
527
  result = re.sub(r'\*(.+?)\*', r'<em>\1</em>', result)
528
  result = re.sub(r'`(.+?)`', r'<code>\1</code>', result)
 
530
  if not result.startswith('<p>'):
531
  result = f'<p>{result}</p>'
532
 
 
 
 
 
 
 
 
 
 
 
 
533
  return result
534
 
535
  def render_thinking_streaming(text: str) -> str:
 
656
  <div style="color: #6b7280; font-size: 0.85rem; line-height: 1.5; margin-top: 0.75rem;">
657
  {html.escape(summary)}
658
  </div>
659
+ <div style="color: #9ca3af; font-size: 0.75rem; margin-top: 0.5rem; font-family: monospace; word-break: break-all;">
660
+ {html.escape(url)}
 
 
 
 
661
  </div>
662
  </div>
663
  </div>
 
1479
  .answer-section a:hover {
1480
  text-decoration: underline;
1481
  }
1482
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1483
  /* User Message Bubble - 淡蓝色背景,右对齐 */
1484
  .user-message-bubble {
1485
  background: linear-gradient(135deg, #e0f2fe 0%, #bae6fd 100%);
 
2066
  color: #f0f9ff !important;
2067
  }
2068
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2069
  /* 用户问题气泡深色模式 */
2070
  .user-message-bubble {
2071
  background: linear-gradient(135deg, #1e3a5f 0%, #1e40af 100%) !important;
 
2198
  color: #e0f2fe !important;
2199
  }
2200
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2201
  .dark .search-result-card {
2202
  background: #1f2937 !important;
2203
  border-color: #374151 !important;
or-logo1.png ADDED

Git LFS Details

  • SHA256: 4d6288904dea6e09ad8ec22bb342309c3bb774a96fc94698798f496649558418
  • Pointer size: 131 Bytes
  • Size of remote file: 618 kB