Download vrag/remote.py from Leon4gr45/openweb: direct link, hf CLI and curl.
- Browser
- Download file 4.1 kB
-
https://huggingface.co/spaces/Leon4gr45/openweb/resolve/main/vrag/remote.py
- Command line
-
hf download hf://spaces/Leon4gr45/openweb/vrag/remote.py
-
curl -L -o remote.py https://huggingface.co/spaces/Leon4gr45/openweb/resolve/main/vrag/remote.py
4.1 kB
| """CPU RAG facade: fail explicitly on incompatible index/provider combinations.""" | |
| import asyncio | |
| import base64 | |
| import hashlib | |
| import json | |
| import os | |
| import time | |
| from datetime import datetime, timezone | |
| import numpy as np | |
| from .config import DATA, INDEX_DIR, VIDEOS_DIR | |
| from .index import get_index | |
| from .providers import ProviderFailure | |
| from .routing import route | |
| from .settings import store | |
| def space_id(provider): | |
| # Endpoint reference plus model and dimension identify a distinct embedding space. | |
| return hashlib.sha256(f'{os.environ.get(provider.base_url_env, "")}:{provider.model}'.encode()).hexdigest()[:16] | |
| async def query(text, config=None): | |
| if config is None: | |
| _, config = store.snapshot() | |
| rule = config.features.get('rag.text_embeddings') | |
| if not rule or not rule.enabled or rule.strategy != 'single': | |
| raise ProviderFailure('embedding_provider_unavailable') | |
| p = config.providers[rule.providers[0]] | |
| manifest_path = get_index().path / 'manifest.json' | |
| manifest = json.loads(manifest_path.read_text()) if manifest_path.exists() else {} | |
| if manifest.get('embedding_space') != space_id(p): | |
| raise ProviderFailure('index_incompatible_reembed_required') | |
| out, statuses = await route(config, 'rag.text_embeddings', {'text': text}) | |
| if out.embedding is None: | |
| raise ProviderFailure(statuses[-1]['status'] if statuses else 'embedding_provider_unavailable') | |
| if len(out.embedding) != manifest.get('dimension'): | |
| raise ProviderFailure('index_dimension_mismatch') | |
| q = np.asarray(out.embedding, dtype=np.float32) | |
| return q / np.linalg.norm(q) | |
| def encode_query(text): | |
| return asyncio.run(query(text)) | |
| def encode_image_query(path): | |
| raise ProviderFailure('image_embeddings_unsupported') | |
| def build_messages(question, hits, use_video, use_audio): | |
| if use_audio: | |
| raise ProviderFailure('rag_audio_unsupported_use_remote_transcription') | |
| text = 'Answer only from these clips and cite [n]. Say when evidence is insufficient.\nQuestion: ' + question | |
| images = [] | |
| for n, h in enumerate(hits, 1): | |
| text += f'\n[{n}] {h["title"]} {h["start"]}-{h["end"]} seconds: {h["text"]}' | |
| if use_video: | |
| # Existing ingestion produces a bounded midpoint frame per segment. Remote models receive bytes, never file://. | |
| frame = VIDEOS_DIR / h['video_id'] / 'segments' / f'{h["idx"]:03d}.jpg' | |
| if frame.exists() and frame.stat().st_size <= 1024 * 1024: | |
| images.append('data:image/jpeg;base64,' + base64.b64encode(frame.read_bytes()).decode()) | |
| return {'text': text[:64000], 'images': images[:8]} | |
| async def _answer(question, view, dim, k, use_video, use_audio): | |
| start = time.monotonic() | |
| _, config = store.snapshot() | |
| hits = get_index().search(await query(question, config), view=view, dim=dim, k=min(k, 8)) | |
| retrieve = time.monotonic() - start | |
| out, statuses = await route(config, 'rag.reasoning', build_messages(question, hits, use_video, use_audio)) | |
| if not out.text: | |
| raise ProviderFailure('reasoning_provider_unavailable') | |
| result = {'question': question, 'answer': out.text, 'clips': hits, | |
| 'settings': {'view': view, 'dim': dim, 'k': k, 'use_video': use_video, 'use_audio': use_audio}, | |
| 'usage': {'prompt_tokens': 0, 'completion_tokens': 0}, 'usage_available': False, | |
| 'provider_results': statuses, 'timing': {'retrieve_s': retrieve, 'generate_s': time.monotonic()-start-retrieve}, | |
| 'created_at': datetime.now(timezone.utc).isoformat()} | |
| if os.environ.get('VRAG_SAVE_ANSWERS', 'true').lower() == 'true': | |
| from .backup.github import state_lock | |
| async with state_lock: | |
| history = DATA / 'answers' / 'history.jsonl' | |
| history.parent.mkdir(parents=True, exist_ok=True) | |
| with history.open('a') as f: | |
| f.write(json.dumps(result) + '\n') | |
| return result | |
| def answer(question, view='text', dim=768, k=4, use_video=True, use_audio=False): | |
| return asyncio.run(_answer(question, view, dim, k, use_video, use_audio)) | |