Adi12345 commited on
Commit
a248cb5
·
verified ·
1 Parent(s): 5d37095

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +11 -808
app.py CHANGED
@@ -1,7 +1,6 @@
1
  """
2
  DVNC.AI — root app.py
3
- Fixed: all internal module imports now use correct underscore names
4
- matching the actual function/constant names in dvnc_ai_v2_hf/.
5
  """
6
 
7
  # ── Standard library ──────────────────────────────────────────────────────
@@ -11,51 +10,8 @@ import re
11
  import sys
12
  from pathlib import Path
13
  from typing import Dict, List, Optional
14
- from dvncuilayout import get_dvnc_layout_css
15
- from dvncaiv2hf.dvncuilayout import get_dvnc_layout_css
16
- try:
17
- from agentroutecards import buildagentroutecardshtml
18
- from discoveryappbridge import (
19
- getdefaultroutestate,
20
- getdiscoverycss,
21
- getinitialdiscoverytimelinehtml,
22
- )
23
- from dvncuilayout import get_dvnc_layout_css
24
- from graphcanvaspatch import rendergraphcanvashtml
25
- from selflearninggraph import (
26
- DEFAULTSOURCES,
27
- SEARCHMODES,
28
- SOURCEOPTIONS,
29
- buildjournalhtml,
30
- ingestselectedpapers,
31
- parseuploadedpdf,
32
- renderparseresult,
33
- runpaperdiscovery,
34
- safetext,
35
- )
36
- except ModuleNotFoundError:
37
- from dvncaiv2hf.agentroutecards import buildagentroutecardshtml
38
- from dvncaiv2hf.discoveryappbridge import (
39
- getdefaultroutestate,
40
- getdiscoverycss,
41
- getinitialdiscoverytimelinehtml,
42
- )
43
- from dvncaiv2hf.dvncuilayout import get_dvnc_layout_css
44
- from dvncaiv2hf.graphcanvaspatch import rendergraphcanvashtml
45
- from dvncaiv2hf.selflearninggraph import
46
- (
47
- DEFAULTSOURCES,
48
- SEARCHMODES,
49
- SOURCEOPTIONS,
50
- buildjournalhtml,
51
- ingestselectedpapers,
52
- parseuploadedpdf,
53
- renderparseresult,
54
- runpaperdiscovery,
55
- safetext,
56
- )
57
 
58
- # Ensure the repository root is on sys.path so the package is importable
59
  ROOT = Path(__file__).resolve().parent
60
  if str(ROOT) not in sys.path:
61
  sys.path.insert(0, str(ROOT))
@@ -84,766 +40,13 @@ from dvnc_ai_v2_hf.self_learning_graph import (
84
  safe_text,
85
  )
86
 
87
- # ── Constants ─────────────────────────────────────────────────────────────
88
- MODELS = [
89
- {
90
- "name": "DVNC Sovereign",
91
- "tag": "flagship",
92
- "desc": "Maximum depth orchestration for frontier discovery",
93
- },
94
- {
95
- "name": "DVNC Atlas",
96
- "tag": "research",
97
- "desc": "Balanced reasoning, graph traversal, and synthesis",
98
- },
99
- {
100
- "name": "DVNC Curie",
101
- "tag": "lab",
102
- "desc": "Experimental hypothesis generation for anomalous signals",
103
- },
104
- ]
105
-
106
- AGENTS = [
107
- "Query Interpreter",
108
- "Graph Divergence Mapper",
109
- "Evidence Harvester",
110
- "Analogy Engine",
111
- "Hypothesis Composer",
112
- "Adversarial Critic",
113
- "Experimental Program Designer",
114
- ]
115
-
116
- NODES = [
117
- {"id": "seed", "label": "Seed Query", "group": "core", "x": 10, "y": 0, "z": 0},
118
- {"id": "bio", "label": "Biomaterials", "group": "domain", "x": 24, "y": 12, "z": -8},
119
- {"id": "card", "label": "Cardiac Repair", "group": "domain", "x": 38, "y": 3, "z": 14},
120
- {"id": "nano", "label": "Nanostructure", "group": "bridge", "x": 24, "y": -18, "z": 16},
121
- {"id": "selfasm", "label": "Self-Assembly", "group": "bridge", "x": 40, "y": -16, "z": -16},
122
- {"id": "electro", "label": "Electro-signalling", "group": "mechanism", "x": 58, "y": 10, "z": -10},
123
- {"id": "immune", "label": "Immune Modulation", "group": "mechanism", "x": 64, "y": -8, "z": 10},
124
- {"id": "trial", "label": "Validation Path", "group": "outcome", "x": 80, "y": 0, "z": 0},
125
- {"id": "alt1", "label": "Piezoelectric Scaffold", "group": "candidate", "x": 56, "y": 26, "z": 14},
126
- {"id": "alt2", "label": "Peptide Mesh", "group": "candidate", "x": 54, "y": -27, "z": -14},
127
- ]
128
-
129
- EDGES = [
130
- ("seed", "bio"), ("seed", "nano"), ("bio", "card"), ("nano", "selfasm"),
131
- ("selfasm", "electro"), ("card", "immune"), ("electro", "trial"),
132
- ("immune", "trial"), ("card", "alt1"), ("selfasm", "alt2"),
133
- ("alt1", "trial"), ("alt2", "trial"),
134
- ]
135
-
136
- DEFAULT_PATH = ["seed", "nano", "selfasm", "electro", "trial"]
137
-
138
- CANDIDATES = [
139
- {
140
- "title": "Piezoelectric Scaffold Cascade",
141
- "front": "Use mechano-electric scaffolds to convert cardiac strain into micro-current signalling.",
142
- "back": "Discovery path: anomalous healing signal -> piezoelectric analog -> ion-channel entrainment -> tissue regeneration. Risk: power density and fibrosis coupling.",
143
- "score": 92,
144
- "novelty": "High",
145
- "agent": "Hypothesis Composer",
146
- },
147
- {
148
- "title": "Peptide Self-Assembly Mesh",
149
- "front": "Deploy dynamic peptide meshes that self-assemble around damaged myocardium and guide repair.",
150
- "back": "Discovery path: self-assembly -> local immune choreography -> regenerative substrate formation. Risk: degradation timing and targeting specificity.",
151
- "score": 88,
152
- "novelty": "High",
153
- "agent": "Analogy Engine",
154
- },
155
- {
156
- "title": "Immune-Tuned Conductive Hydrogel",
157
- "front": "Blend conductivity with macrophage-state modulation to reduce scarring and restore conduction.",
158
- "back": "Discovery path: inflammation mismatch -> conductive medium -> macrophage polarization -> synchronized healing. Risk: persistence and biocompatibility.",
159
- "score": 85,
160
- "novelty": "Medium-High",
161
- "agent": "Adversarial Critic",
162
- },
163
- ]
164
-
165
- ACADEMIC_INSIGHTS = [
166
- {
167
- "hypothesis": "Implementation of mechano-electric scaffolds to transduce cardiac strain into localized micro-current signalling for myocardial regeneration.",
168
- "metrics": {
169
- "Novelty": 92,
170
- "Mechanistic clarity": 85,
171
- "Experimental tractability": 78,
172
- "Cross-domain distance": 94,
173
- },
174
- "outline": (
175
- "1. Synthesize candidate piezoelectric biomaterial scaffolds with tunable strain-electric coupling.\n"
176
- "2. Evaluate in vitro electromechanical transduction and subsequent ion-channel entrainment.\n"
177
- "3. Conduct in vivo comparative models to assess regenerative efficacy against gold-standard substrates.\n"
178
- "4. Rigorously validate to exclude pathological fibrosis and power-density toxicity."
179
- ),
180
- "path": ["seed", "bio", "card", "alt1", "trial"],
181
- },
182
- {
183
- "hypothesis": "Deployment of dynamic peptide networks that self-assemble post-infarction to orchestrate local immunological responses and guide substrate regeneration.",
184
- "metrics": {
185
- "Novelty": 88,
186
- "Mechanistic clarity": 82,
187
- "Experimental tractability": 86,
188
- "Cross-domain distance": 85,
189
- },
190
- "outline": (
191
- "1. Formulate peptide sequences programmed for triggered in situ self-assembly within the myocardial infarct zone.\n"
192
- "2. Quantify macrophage polarization and local immune choreography post-deployment.\n"
193
- "3. Map the temporospatial degradation profile against de novo tissue formation.\n"
194
- "4. Falsify against off-target aggregation and delayed clearance risks."
195
- ),
196
- "path": ["seed", "nano", "selfasm", "alt2", "trial"],
197
- },
198
- {
199
- "hypothesis": "Integration of conductive hydrogels with immunomodulatory properties to simultaneously bridge electrical uncoupling and mitigate adverse fibrotic scarring.",
200
- "metrics": {
201
- "Novelty": 85,
202
- "Mechanistic clarity": 90,
203
- "Experimental tractability": 88,
204
- "Cross-domain distance": 79,
205
- },
206
- "outline": (
207
- "1. Fabricate biocompatible hydrogels featuring precisely tuned electrical conductivity and immunomodulatory motifs.\n"
208
- "2. Monitor electrophysiological synchronization across the scaffold-tissue interface.\n"
209
- "3. Assess macrophage state transitions and suppression of adverse fibrotic remodelling.\n"
210
- "4. Validate long-term persistence, hemocompatibility, and mechanical integration."
211
- ),
212
- "path": ["seed", "bio", "card", "immune", "trial"],
213
- },
214
- ]
215
-
216
- # ── Utility helpers ───────────────────────────────────────────────────────
217
-
218
- def norm_text(x: Optional[str]) -> str:
219
- return re.sub(r"\s+", " ", (x or "")).strip()
220
-
221
-
222
- def build_learning_graph_html(nodes, edges, title="Self-Learning Knowledge Graph"):
223
- return render_graph_canvas_html(
224
- {
225
- "status": "ok" if (nodes or edges) else "empty",
226
- "nodes": nodes or [],
227
- "edges": edges or [],
228
- },
229
- title=title,
230
- height=780,
231
- )
232
-
233
- # ── HTML builders ─────────────────────────────────────────────────────────
234
-
235
- def build_connectome_html(path_ids: List[str]) -> str:
236
- active = set(path_ids)
237
- node_map = {n["id"]: n for n in NODES}
238
- path_pairs = {
239
- pair
240
- for i in range(len(path_ids) - 1)
241
- for pair in [(path_ids[i], path_ids[i + 1]), (path_ids[i + 1], path_ids[i])]
242
- }
243
- baselines, activelines, circles, labels = [], [], [], []
244
- for a, b in EDGES:
245
- na, nb = node_map[a], node_map[b]
246
- x1, y1 = na["x"] * 8 + 80, na["y"] * 6 + 280
247
- x2, y2 = nb["x"] * 8 + 80, nb["y"] * 6 + 280
248
- baselines.append(f'e class="edge" x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}"/>')
249
- if (a, b) in path_pairs:
250
- activelines.append(f'e class="edge active" x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}"/>')
251
- for n in NODES:
252
- cx, cy = n["x"] * 8 + 80, n["y"] * 6 + 280
253
- is_active = n["id"] in active
254
- state = "chosen" if is_active else "idle"
255
- halo_cls = "halo active" if is_active else "halo"
256
- lbl_cls = "label active" if is_active else "label"
257
- radius = 18 if is_active else 13
258
- halo_r = 30 if is_active else 0
259
- circles.append(
260
- f'ircle class="{halo_cls}" cx="{cx}" cy="{cy}" r="{halo_r}"/>'
261
- f'ircle class="node {state}" cx="{cx}" cy="{cy}" r="{radius}"/>'
262
- f'<title>{safe_text(n["label"])}</title>'
263
- f'<text class="{lbl_cls}" x="{cx}" y="{cy + radius + 14}" text-anchor="middle">{safe_text(n["label"][:18])}</text>'
264
- )
265
- return f"""<div class="brain-shell panel">
266
- <div class="brain-header">
267
- <div><p class="eyebrow">Connectome</p><h3>3D Connectome</h3></div>
268
- <div class="brain-legend">
269
- <span><span class="dot dot-live"></span>lit path</span>
270
- <span><span class="dot dot-chosen"></span>chosen node</span>
271
- <span><span class="dot dot-idle"></span>available node</span>
272
- </div></div>
273
- <div class="brain-stage">
274
- <svg class="brain-svg" viewBox="0 0 880 560">
275
- {''.join(baselines)} {''.join(activelines)} {''.join(circles)}
276
- </svg></div></div>"""
277
-
278
-
279
- def build_cards_html(cards: List[Dict]) -> str:
280
- items = []
281
- for i, c in enumerate(cards):
282
- items.append(
283
- f"""<div class="candidate-card" tabindex="0">
284
- <div class="candidate-card-inner">
285
- <div class="candidate-face">
286
- <div class="candidate-top"><span class="chip">{safe_text(c["agent"])}</span><span class="score">{safe_text(c["score"])}</span></div>
287
- <h4>{safe_text(c["title"])}</h4>
288
- <p>{safe_text(c["front"])}</p>
289
- <div class="meta-row"><span>Novelty <strong>{safe_text(c["novelty"])}</strong></span></div>
290
- <button class="mini" onclick="triggerRouteSwap({i})">Use as main insight</button>
291
- </div>
292
- <div class="candidate-face candidate-back">
293
- <div class="candidate-top"><span class="chip alt">Alternative path</span><span class="score">{safe_text(c["score"])}</span></div>
294
- <h4>{safe_text(c["title"])}</h4>
295
- <p>{safe_text(c["back"])}</p>
296
- <div class="meta-row"><span>Swap into route <strong>Enabled</strong></span></div>
297
- <button class="mini" onclick="triggerRouteSwap({i})">Use as main insight</button>
298
- </div>
299
- </div></div>"""
300
- )
301
- return '<div class="candidate-grid">' + "".join(items) + "</div>"
302
-
303
-
304
- def build_chat_html(query: str, result: Dict) -> str:
305
- return f"""<div class="chat-panel panel"><div class="chat-thread">
306
- <div class="bubble bubble-user"><span class="role">You</span><p>{safe_text(query)}</p></div>
307
- <div class="bubble bubble-ai"><span class="role">DVNC Sovereign</span><p>{safe_text(result["summary"])}</p></div>
308
- <div class="bubble bubble-system"><span class="role">Discovery Signal</span>
309
- <p><strong>Primary hypothesis:</strong> {safe_text(result["primary_hypothesis"])}</p>
310
- </div></div></div>"""
311
-
312
-
313
- def build_models_html(selected: str) -> str:
314
- items = []
315
- for m in MODELS:
316
- active = "active" if m["name"] == selected else ""
317
- items.append(
318
- f'<div class="model-pill {active}"><span class="model-name">{safe_text(m["name"])}</span>'
319
- f'<span class="model-tag">{safe_text(m["tag"])}</span>'
320
- f'<small>{safe_text(m["desc"])}</small></div>'
321
- )
322
- return '<div class="model-switcher">' + "".join(items) + "</div>"
323
-
324
- # ── Discovery logic ───────────────────────────────────────────────────────
325
-
326
- def run_discovery(query: str, model_name: str):
327
- random.seed(len(query or "") + len(model_name or ""))
328
- if "curie" in (query or "").lower() or "einstein" in (query or "").lower():
329
- primary = "Map the anomaly first, then force a distant analogy before composing the experimental programme."
330
- path = ["seed", "bio", "card", "immune", "trial"]
331
- else:
332
- primary = (
333
- "Utilization of a self-assembling conductive scaffold to transduce mechanical "
334
- "strain into localized regenerative signalling pathways."
335
- )
336
- path = DEFAULT_PATH
337
-
338
- summaries = [
339
- "Normalises the user prompt into a graph-searchable seed and isolates the tension inside the question.",
340
- "Finds remote conceptual bridges instead of staying near the starting domain cluster.",
341
- "Pulls evidence packets and conflict signals required for grounded hypothesis formation.",
342
- "Generates cross-domain analogies with a bias toward mechanism transfer rather than keyword similarity.",
343
- "Composes the lead hypothesis and two structurally different variants.",
344
- "Attacks weak assumptions, hidden confounders, and feasibility gaps.",
345
- "Produces a staged validation plan with measurable falsification criteria.",
346
- ]
347
- tags = ["input", "graph", "evidence", "analogy", "compose", "critique", "experiment"]
348
- reasoning = [
349
- {"step": i + 1, "agent": AGENTS[i], "tag": tags[i], "summary": summaries[i]}
350
- for i in range(7)
351
- ]
352
- result = {
353
- "summary": (
354
- "A deeper route was chosen through the connectome, with live alternatives preserved "
355
- "as swappable cards so the reasoning path can be inspected rather than hidden."
356
- ),
357
- "primary_hypothesis": primary,
358
- "reasoning": reasoning,
359
- "cards": CANDIDATES,
360
- "path": path,
361
- "metrics": {
362
- "Novelty": 93,
363
- "Mechanistic clarity": 89,
364
- "Experimental tractability": 82,
365
- "Cross-domain distance": 91,
366
- },
367
- }
368
- chat_html = build_chat_html(query, result)
369
- connectome_html = build_connectome_html(path)
370
- timeline_html = build_agent_route_cards_html(reasoning)
371
- metrics_md = "\n".join(f"- {k}: {v}/100" for k, v in result["metrics"].items())
372
- hypothesis_md = (
373
- "# Discovery Output\n\n"
374
- f"**Model:** {model_name}\n\n"
375
- f"**Primary hypothesis:** {result['primary_hypothesis']}\n\n"
376
- "## Scoring\n"
377
- f"{metrics_md}\n\n"
378
- "## Experimental outline\n"
379
- "1. Construct the candidate material or protocol.\n"
380
- "2. Test mechanistic signal expression under controlled conditions.\n"
381
- "3. Compare against baseline and nearest-neighbour alternatives.\n"
382
- "4. Falsify using the adversarial risk criteria surfaced in the reasoning path.\n"
383
- )
384
- cards_html = build_cards_html(CANDIDATES)
385
- route_state = get_default_route_state()
386
- return (
387
- chat_html,
388
- connectome_html,
389
- timeline_html,
390
- cards_html,
391
- hypothesis_md,
392
- build_models_html(model_name),
393
- route_state,
394
- )
395
-
396
-
397
- def apply_route_swap(query: str, model_name: str, route_swap_payload: str, route_state):
398
  try:
399
- idx = int(route_swap_payload)
400
- except Exception:
401
- idx = 0
402
- if not (0 <= idx < len(ACADEMIC_INSIGHTS)):
403
- idx = 0
404
- academic = ACADEMIC_INSIGHTS[idx]
405
- connectome_html = build_connectome_html(academic["path"])
406
- result = {
407
- "summary": (
408
- "Main insight formally adopted. The connectome pathway and validation protocol "
409
- "have been realigned to the selected candidate methodology."
410
- ),
411
- "primary_hypothesis": academic["hypothesis"],
412
- }
413
- chat_html = build_chat_html(query, result)
414
- metrics_md = "\n".join(f"- {k}: {v}/100" for k, v in academic["metrics"].items())
415
- hypothesis_md = (
416
- "# Discovery Output\n\n"
417
- f"**Model:** {model_name}\n\n"
418
- f"**Primary hypothesis:** {academic['hypothesis']}\n\n"
419
- "## Scoring\n"
420
- f"{metrics_md}\n\n"
421
- "## Experimental outline\n"
422
- f"{academic['outline']}\n"
423
- )
424
- return chat_html, connectome_html, gr.update(), hypothesis_md, route_state
425
-
426
- # ── Example loaders ──────────────────────────────────────────────────────
427
-
428
- def load_example() -> str:
429
- return "How could a self-assembling conductive biomaterial improve cardiac tissue regeneration by converting mechanical strain into repair signalling?"
430
-
431
-
432
- def load_paper_topic() -> str:
433
- return "self-assembling conductive biomaterials for cardiac repair"
434
-
435
- # ── CSS / HEAD ────────────────────────────────────────────────────────────
436
-
437
- BASE_CSS = r"""
438
- :root {
439
- --bg: #ffffff;
440
- --panel: #ffffff;
441
- --line: rgba(0,0,0,.12);
442
- --text: #111111;
443
- --muted: #5b5b5b;
444
- --soft: rgba(0,0,0,.62);
445
- --gold: #ff6600;
446
- --teal: #17b8a6;
447
- --blue: #628dff;
448
- --chosen: #ff7a1a;
449
- --idle: #b8d8ff;
450
- --idle-stroke: #5e8fe6;
451
- --query-node: #ffd8b3;
452
- --paper-node: #d7f6f2;
453
- --upload-node: #e7defe;
454
- --shadow: 0 16px 40px rgba(0,0,0,.12);
455
- }
456
-
457
- html, body, .gradio-container {
458
- background: #ffffff !important;
459
- font-family: Inter, ui-sans-serif, system-ui, sans-serif;
460
- }
461
-
462
- .gradio-container {
463
- max-width: 1640px !important;
464
- padding: 20px !important;
465
- }
466
-
467
- #dvnc-shell {
468
- border: 1px solid var(--line);
469
- border-radius: 28px;
470
- overflow: hidden;
471
- background: #ffffff;
472
- box-shadow: var(--shadow);
473
- padding: 20px 22px 22px;
474
- }
475
-
476
- .hero-bar {
477
- display: flex;
478
- justify-content: space-between;
479
- align-items: center;
480
- gap: 16px;
481
- padding-bottom: 12px;
482
- border-bottom: 1px solid rgba(0,0,0,.06);
483
- margin-bottom: 16px;
484
- }
485
-
486
- .brand {
487
- display: flex;
488
- align-items: center;
489
- gap: 14px;
490
- }
491
-
492
- .logo {
493
- width: 42px;
494
- height: 42px;
495
- border-radius: 14px;
496
- display: grid;
497
- place-items: center;
498
- color: var(--gold);
499
- background: linear-gradient(135deg, rgba(255,122,26,.12), rgba(23,184,166,.10));
500
- border: 1px solid rgba(0,0,0,.08);
501
- }
502
-
503
- .logo svg {
504
- width: 24px;
505
- height: 24px;
506
- }
507
-
508
- .brand h1 {
509
- font-size: 1.05rem;
510
- margin: 0;
511
- font-weight: 700;
512
- letter-spacing: .12em;
513
- text-transform: uppercase;
514
- }
515
-
516
- .brand p {
517
- margin: 3px 0 0;
518
- color: var(--muted);
519
- font-size: .84rem;
520
- }
521
-
522
- .status {
523
- display: flex;
524
- gap: 10px;
525
- align-items: center;
526
- color: var(--soft);
527
- font-size: .85rem;
528
- }
529
-
530
- .status-dot {
531
- width: 10px;
532
- height: 10px;
533
- border-radius: 50%;
534
- background: var(--teal);
535
- box-shadow: 0 0 0 6px rgba(23,184,166,.10), 0 0 14px rgba(23,184,166,.25);
536
- }
537
-
538
- .panel {
539
- background: #ffffff;
540
- border: 1px solid var(--line);
541
- border-radius: 22px;
542
- box-shadow: inset 0 1px 0 rgba(255,255,255,.8);
543
- }
544
-
545
- .querybox textarea,
546
- .querybox input {
547
- background: transparent !important;
548
- color: var(--text) !important;
549
- }
550
-
551
- .querybox,
552
- .querybox > div {
553
- background: #ffffff !important;
554
- border-radius: 18px !important;
555
- border-color: var(--line) !important;
556
- }
557
-
558
- .chat-panel {
559
- padding: 18px;
560
- min-height: 280px;
561
- }
562
-
563
- .chat-thread {
564
- display: flex;
565
- flex-direction: column;
566
- gap: 14px;
567
- }
568
-
569
- .bubble {
570
- max-width: 88%;
571
- padding: 16px 18px;
572
- border-radius: 22px;
573
- border: 1px solid var(--line);
574
- }
575
-
576
- .bubble p {
577
- margin: 8px 0 0;
578
- line-height: 1.6;
579
- font-size: .96rem;
580
- color: var(--text);
581
- }
582
-
583
- .bubble .role {
584
- font-size: .72rem;
585
- letter-spacing: .12em;
586
- text-transform: uppercase;
587
- color: var(--muted);
588
- }
589
-
590
- .bubble-user {
591
- align-self: flex-end;
592
- background: linear-gradient(135deg, rgba(98,141,255,.16), rgba(98,141,255,.08));
593
- }
594
-
595
- .bubble-ai {
596
- align-self: flex-start;
597
- background: #ffffff;
598
- }
599
-
600
- .bubble-system {
601
- align-self: flex-start;
602
- background: linear-gradient(135deg, rgba(255,122,26,.10), rgba(255,122,26,.04));
603
- }
604
-
605
- .model-switcher {
606
- display: grid;
607
- grid-template-columns: repeat(3,1fr);
608
- gap: 12px;
609
- }
610
-
611
- .model-pill {
612
- padding: 14px;
613
- border: 1px solid var(--line);
614
- border-radius: 18px;
615
- display: flex;
616
- flex-direction: column;
617
- gap: 4px;
618
- min-height: 98px;
619
- background: #ffffff;
620
- }
621
-
622
- .model-pill.active {
623
- border-color: rgba(255,122,26,.40);
624
- background: linear-gradient(135deg, rgba(255,122,26,.10), rgba(255,255,255,.96));
625
- }
626
-
627
- .model-name {
628
- font-weight: 650;
629
- color: var(--text);
630
- }
631
-
632
- .model-tag {
633
- font-size: .76rem;
634
- text-transform: uppercase;
635
- letter-spacing: .12em;
636
- color: var(--gold);
637
- }
638
-
639
- .model-pill small {
640
- color: var(--muted);
641
- line-height: 1.45;
642
- }
643
-
644
- .brain-shell {
645
- padding: 18px;
646
- }
647
-
648
- .brain-header {
649
- display: flex;
650
- justify-content: space-between;
651
- align-items: flex-end;
652
- gap: 16px;
653
- margin-bottom: 10px;
654
- }
655
-
656
- .eyebrow {
657
- font-size: .72rem;
658
- letter-spacing: .16em;
659
- text-transform: uppercase;
660
- color: var(--gold);
661
- margin: 0 0 4px;
662
- }
663
-
664
- .brain-header h3 {
665
- margin: 0;
666
- font-size: 1.12rem;
667
- color: var(--text);
668
- }
669
-
670
- .brain-legend {
671
- display: flex;
672
- gap: 14px;
673
- color: var(--muted);
674
- font-size: .8rem;
675
- flex-wrap: wrap;
676
- }
677
-
678
- .dot {
679
- width: 10px;
680
- height: 10px;
681
- display: inline-block;
682
- border-radius: 50%;
683
- margin-right: 6px;
684
- }
685
-
686
- .dot-live {
687
- background: var(--chosen);
688
- box-shadow: 0 0 10px rgba(255,122,26,.35);
689
- }
690
-
691
- .dot-chosen {
692
- background: var(--chosen);
693
- }
694
-
695
- .dot-idle {
696
- background: var(--idle);
697
- border: 1px solid var(--idle-stroke);
698
- }
699
-
700
- .dot-query {
701
- background: var(--query-node);
702
- border: 1px solid #de9e58;
703
- }
704
-
705
- .dot-paper {
706
- background: var(--paper-node);
707
- border: 1px solid #4fb3a5;
708
- }
709
-
710
- .dot-upload {
711
- background: var(--upload-node);
712
- border: 1px solid #8f73d9;
713
- }
714
-
715
- .timeline {
716
- display: flex;
717
- flex-direction: column;
718
- gap: 10px;
719
- }
720
-
721
- .agent-step {
722
- border: 1px solid var(--line);
723
- border-radius: 18px;
724
- background: #ffffff;
725
- overflow: hidden;
726
- }
727
-
728
- .agent-summary {
729
- list-style: none;
730
- display: grid;
731
- grid-template-columns: 42px 1fr;
732
- gap: 12px;
733
- align-items: center;
734
- padding: 12px;
735
- cursor: pointer;
736
- }
737
-
738
- .agent-summary::-webkit-details-marker {
739
- display: none;
740
- }
741
-
742
- .agent-index {
743
- width: 42px;
744
- height: 42px;
745
- border-radius: 14px;
746
- display: grid;
747
- place-items: center;
748
- font-weight: 700;
749
- color: var(--gold);
750
- background: rgba(255,122,26,.08);
751
- border: 1px solid rgba(255,122,26,.18);
752
- }
753
-
754
- .agent-head {
755
- display: flex;
756
- justify-content: space-between;
757
- gap: 12px;
758
- align-items: center;
759
- }
760
-
761
- .agent-head h4 {
762
- margin: 0;
763
- font-size: .98rem;
764
- color: var(--text);
765
- }
766
-
767
- .agent-head span {
768
- font-size: .72rem;
769
- letter-spacing: .12em;
770
- text-transform: uppercase;
771
- color: var(--muted);
772
- }
773
-
774
- .agent-copy {
775
- padding: 0 14px 16px 66px;
776
- }
777
-
778
- .agent-copy p {
779
- margin: 0;
780
- color: #2d2d2d;
781
- font-size: .93rem;
782
- line-height: 1.6;
783
- }
784
-
785
- .candidate-grid {
786
- display: grid;
787
- grid-template-columns: repeat(3,minmax(0,1fr));
788
- gap: 18px;
789
- }
790
-
791
- .candidate-card {
792
- background: none;
793
- perspective: 1400px;
794
- min-height: 330px;
795
- }
796
-
797
- .candidate-card-inner {
798
- position: relative;
799
- width: 100%;
800
- min-height: 330px;
801
- transition: transform .8s cubic-bezier(.2,.7,.1,1);
802
- transform-style: preserve-3d;
803
- }
804
-
805
- .candidate-card:hover .candidate-card-inner,
806
- .candidate-card:focus .candidate-card-inner,
807
- .candidate-card:focus-within .candidate-card-inner {
808
- transform: rotateY(180deg);
809
- }
810
-
811
- .candidate-face {
812
- position: absolute;
813
- inset: 0;
814
- padding: 20px;
815
- border-radius: 22px;
816
- border: 1px solid var(--line);
817
- background: #ffffff;
818
- color: var(--text);
819
- backface-visibility: hidden;
820
- box-shadow: 0 12px 24px rgba(0,0,0,.06);
821
- display: flex;
822
- flex-direction: column;
823
- gap: 14px;
824
- }
825
-
826
- .candidate-back {
827
- transform: rotateY(180deg);
828
- }
829
-
830
- .paper-card,
831
- .parse-card,
832
- .journal-card {
833
- border: 1px solid var(--line);
834
- border-radius: 18px;
835
- background: #ffffff;
836
- }
837
-
838
- footer {
839
- display: none !important;
840
- }
841
-
842
- @media (max-width: 1180px) {
843
- .model-switcher,
844
- .candidate-grid {
845
- grid-template-columns: 1fr;
846
- }
847
- }
848
- """
849
- CSS = BASE_CSS + "\n" + get_dvnc_layout_css() + "\n" + getdiscoverycss()
 
1
  """
2
  DVNC.AI — root app.py
3
+ Fixed: corrected all imports to use dvnc_ai_v2_hf package with proper underscore function names.
 
4
  """
5
 
6
  # ── Standard library ──────────────────────────────────────────────────────
 
10
  import sys
11
  from pathlib import Path
12
  from typing import Dict, List, Optional
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
+ # Ensure repository root is on sys.path
15
  ROOT = Path(__file__).resolve().parent
16
  if str(ROOT) not in sys.path:
17
  sys.path.insert(0, str(ROOT))
 
40
  safe_text,
41
  )
42
 
43
+ # ── Simplified launcher: use existing app from dvnc_ai_v2_hf ─────────────
44
+ if __name__ == "__main__":
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  try:
46
+ from dvnc_ai_v2_hf import app as internal_app
47
+ internal_app.demo.launch()
48
+ except (ImportError, AttributeError):
49
+ print("Could not import dvnc_ai_v2_hf.app falling back to minimal Gradio demo")
50
+ with gr.Blocks() as demo:
51
+ gr.Markdown("# DVNC.AI\n\nSpace configuration in progress. Check Files tab for dvnc_ai_v2_hf/app.py")
52
+ demo.launch()