openweb / tests /test_rag.py
Leon4gr45's picture
Upload folder using huggingface_hub
33962ff verified
Raw History Blame Contribute Delete
4.6 kB
import asyncio
import json
import numpy as np
import pytest
from fastapi.testclient import TestClient
from config.schema import Configuration, Provider, Route
from vrag.api import app
from vrag.index import get_index
from vrag.providers import Output, ProviderFailure
from vrag.remote import space_id, query, build_messages
from vrag.settings import store
@pytest.fixture
def corpus(tmp_path,monkeypatch):
monkeypatch.setattr('vrag.remote.DATA',tmp_path)
index=tmp_path/'index';index.mkdir();videos=tmp_path/'videos';videos.mkdir()
video=videos/'v1';video.mkdir();(video/'segments').mkdir()
seg={'id':'v1_000','video_id':'v1','title':'Demo','idx':0,'start':1,'end':3,'text':'a hand'}
(index/'segments.json').write_text(json.dumps([seg]));np.save(index/'text.npy',np.array([[1.,0.,0.]],dtype='float32'))
(video/'meta.json').write_text(json.dumps({'id':'v1','title':'Demo','duration':10}))
(video/'segments.json').write_text(json.dumps([seg]))
from PIL import Image
Image.new('RGB',(20,20)).save(video/'segments/000.jpg')
monkeypatch.setenv('URL','https://example.com/v1');monkeypatch.setenv('VM_USER_TOKEN','u'*32)
p=Provider(adapter='openai-embeddings',base_url_env='URL',model='embedding',capabilities=['text_embeddings'],trust='approved_sensitive')
vlm=Provider(adapter='openai-chat-vision',base_url_env='URL',model='vision',capabilities=['image_understanding','reasoning'],trust='approved_sensitive')
old=store.history,store.version
store.history=[Configuration(providers={'emb':p,'vlm':vlm},features={'rag.text_embeddings':Route(providers=['emb']),'rag.reasoning':Route(providers=['vlm'])})];store.version=1
(index/'manifest.json').write_text(json.dumps({'embedding_space':space_id(p),'dimension':3}))
for mod in ['vrag.index','vrag.api','vrag.remote']:
monkeypatch.setattr(mod+'.INDEX_DIR',index)
for mod in ['vrag.api','vrag.remote']:
monkeypatch.setattr(mod+'.VIDEOS_DIR',videos)
get_index.cache_clear()
async def call(name,p,payload,sensitive):
if name=='emb':return Output(embedding=[1,0,0])
assert all(not im.startswith('file:') for im in payload.get('images',[]))
return Output(text='A hand is visible [1].')
monkeypatch.setattr('vrag.routing.adapter.call',call)
yield seg,index
store.history,store.version=old;get_index.cache_clear()
def test_library_search_ask_regression(corpus):
with TestClient(app,headers={'Authorization':'Bearer '+'u'*32}) as c:
assert len(c.get('/api/videos').json())==1
assert c.get('/api/videos/v1').json()['segments'][0]['start']==1
r=c.get('/api/search?q=hand&view=text&dim=3')
assert r.status_code==200,r.text
assert r.json()['hits'][0]['id']=='v1_000'
r=c.post('/api/ask',json={'question':'what is shown?','view':'text','dim':3})
assert r.status_code==200,r.text
assert '[1]' in r.json()['answer'] and r.json()['clips'][0]['start']==1
assert c.get('/api/search?q=x&view=text&dim=128').status_code==400
@pytest.mark.asyncio
async def test_incompatible_model_and_endpoint_requires_reembedding(corpus,monkeypatch):
monkeypatch.setenv('URL','https://different.example/v1')
with pytest.raises(ProviderFailure,match='index_incompatible'):
await query('hi')
def test_bounded_frame_fallback(corpus):
payload=build_messages('question',[corpus[0]],True,False)
assert payload['images'][0].startswith('data:image/jpeg;base64,')
assert '[1]' in payload['text'] and '1-3 seconds' in payload['text']
with pytest.raises(ProviderFailure):build_messages('q',[corpus[0]],False,True)
def test_media_range(tmp_path):
# Same Starlette handler used by production media mounting.
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
(tmp_path/'clip.mp4').write_bytes(b'0123456789')
a=FastAPI();a.mount('/media',StaticFiles(directory=tmp_path))
with TestClient(a) as c:
r=c.get('/media/clip.mp4',headers={'Range':'bytes=2-5'})
assert r.status_code==206 and r.content==b'2345'
def test_corrupt_vector_manifest_is_rejected(corpus):
_,index=corpus
np.save(index/'text.npy',np.array([[float('nan'),0,1]],dtype='float32'))
get_index.cache_clear()
with pytest.raises(ProviderFailure,match='index_invalid'):get_index()
def test_vector_rows_must_match_segment_manifest(corpus):
_,index=corpus
np.save(index/'text.npy',np.array([[1,0,0],[0,1,0]],dtype='float32'))
get_index.cache_clear()
with pytest.raises(ProviderFailure,match='index_invalid'):get_index()