├── .github ├── ISSUE_TEMPLATE │ ├── verba-feature-template.md │ └── verba-issue-template.md └── workflows │ └── docker-image.yml ├── .gitignore ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Dockerfile ├── FRONTEND.md ├── LICENSE ├── MANIFEST.in ├── PYTHON_TUTORIAL.md ├── README.md ├── TECHNICAL.md ├── docker-compose.yml ├── frontend ├── .eslintrc.json ├── .gitignore ├── app │ ├── api.ts │ ├── components │ │ ├── Chat │ │ │ ├── ChatConfig.tsx │ │ │ ├── ChatInterface.tsx │ │ │ ├── ChatMessage.tsx │ │ │ ├── ChatView.tsx │ │ │ └── StatusLabel.tsx │ │ ├── Document │ │ │ ├── ChunkView.tsx │ │ │ ├── ContentView.tsx │ │ │ ├── DocumentExplorer.tsx │ │ │ ├── DocumentMetaView.tsx │ │ │ ├── DocumentSearch.tsx │ │ │ ├── DocumentView.tsx │ │ │ ├── VectorView.tsx │ │ │ └── util.ts │ │ ├── Ingestion │ │ │ ├── BasicSettingView.tsx │ │ │ ├── ComponentView.tsx │ │ │ ├── ConfigurationView.tsx │ │ │ ├── FileComponent.tsx │ │ │ ├── FileSelectionView.tsx │ │ │ └── IngestionView.tsx │ │ ├── Login │ │ │ ├── GettingStarted.tsx │ │ │ └── LoginView.tsx │ │ ├── Navigation │ │ │ ├── InfoComponent.tsx │ │ │ ├── NavButton.tsx │ │ │ ├── NavbarComponent.tsx │ │ │ ├── StatusMessenger.tsx │ │ │ ├── UserModal.tsx │ │ │ ├── VerbaButton.tsx │ │ │ └── util.ts │ │ └── Settings │ │ │ ├── InfoView.tsx │ │ │ ├── SettingsComponent.tsx │ │ │ ├── SettingsView.tsx │ │ │ └── SuggestionView.tsx │ ├── globals.css │ ├── layout.tsx │ ├── page.tsx │ ├── types.ts │ └── util.ts ├── glsl.d.ts ├── next.config.js ├── package-lock.json ├── package.json ├── postcss.config.js ├── public │ ├── alps_field_1k.hdr │ ├── cloudy.hdr │ ├── cool_cap.png │ ├── fire_cap.png │ ├── gold_matcap.png │ ├── golden_cap.png │ ├── ice_cap.png │ ├── icon.ico │ ├── macbook.gltf │ ├── next.svg │ ├── shaders │ │ ├── includes │ │ │ └── simplexNoise4d.glsl │ │ └── wobble │ │ │ ├── fragment.glsl │ │ │ └── vertex.glsl │ ├── shiny_cap.png │ ├── silver_cap.png │ ├── verba.glb │ ├── verba.gltf │ ├── verba.png │ ├── vercel.svg │ ├── weaviate.glb │ └── weaviate.png ├── tailwind.config.ts └── tsconfig.json ├── goldenverba ├── .env.example ├── __init__.py ├── components │ ├── __init__.py │ ├── chunk.py │ ├── chunking │ │ ├── CodeChunker.py │ │ ├── HTMLChunker.py │ │ ├── JSONChunker.py │ │ ├── MarkdownChunker.py │ │ ├── RecursiveChunker.py │ │ ├── SemanticChunker.py │ │ ├── SentenceChunker.py │ │ ├── TokenChunker.py │ │ ├── __init__.py │ │ └── chunking_examples.py │ ├── document.py │ ├── embedding │ │ ├── CohereEmbedder.py │ │ ├── GoogleEmbedder.py │ │ ├── OllamaEmbedder.py │ │ ├── OpenAIEmbedder.py │ │ ├── SentenceTransformersEmbedder.py │ │ ├── UpstageEmbedder.py │ │ ├── VoyageAIEmbedder.py │ │ ├── WeaviateEmbedder.py │ │ └── __init__.py │ ├── generation │ │ ├── AnthrophicGenerator.py │ │ ├── CohereGenerator.py │ │ ├── GeminiGenerator.py │ │ ├── GroqGenerator.py │ │ ├── NovitaGenerator.py │ │ ├── OllamaGenerator.py │ │ ├── OpenAIGenerator.py │ │ ├── UpstageGenerator.py │ │ └── __init__.py │ ├── interfaces.py │ ├── managers.py │ ├── reader │ │ ├── AssemblyAIAPI.py │ │ ├── BasicReader.py │ │ ├── FirecrawlReader.py │ │ ├── GitReader.py │ │ ├── HTMLReader.py │ │ ├── UnstructuredAPI.py │ │ ├── UpstageDocumentParse.py │ │ └── __init__.py │ ├── retriever │ │ ├── WindowRetriever.py │ │ └── __init__.py │ ├── types.py │ └── util.py ├── server │ ├── __init__.py │ ├── api.py │ ├── cli.py │ ├── frontend │ │ └── out │ │ │ ├── 404.html │ │ │ ├── _next │ │ │ └── static │ │ │ │ ├── 30i2FQTbR7Y4f-UfM6hbP │ │ │ │ ├── _buildManifest.js │ │ │ │ └── _ssgManifest.js │ │ │ │ ├── 4ajn2kvxlVqvDvSUh7-up │ │ │ │ ├── _buildManifest.js │ │ │ │ └── _ssgManifest.js │ │ │ │ ├── 5piNIBwi9EVvWEGUCt1HJ │ │ │ │ ├── _buildManifest.js │ │ │ │ └── _ssgManifest.js │ │ │ │ ├── 5rVRk1H0CSx_t9B72OCkV │ │ │ │ ├── _buildManifest.js │ │ │ │ └── _ssgManifest.js │ │ │ │ ├── CZvV6ohXKOaM2HZQjSr_e │ │ │ │ ├── _buildManifest.js │ │ │ │ └── _ssgManifest.js │ │ │ │ ├── EK3SdW_8_2ZVH1NNgqlNv │ │ │ │ ├── _buildManifest.js │ │ │ │ └── _ssgManifest.js │ │ │ │ ├── FEflRPdxwBXOroRwOpEz6 │ │ │ │ ├── _buildManifest.js │ │ │ │ └── _ssgManifest.js │ │ │ │ ├── FcSX1HknjNhe9H0xxw_uy │ │ │ │ ├── _buildManifest.js │ │ │ │ └── _ssgManifest.js │ │ │ │ ├── I01L2Qf2M5E8rKySVdfwz │ │ │ │ ├── _buildManifest.js │ │ │ │ └── _ssgManifest.js │ │ │ │ ├── KoV36dmdEgYXG0yvTGe3m │ │ │ │ ├── _buildManifest.js │ │ │ │ └── _ssgManifest.js │ │ │ │ ├── MYxb6oMzMgqonOwG97TqG │ │ │ │ ├── _buildManifest.js │ │ │ │ └── _ssgManifest.js │ │ │ │ ├── QPYBqPy_EgcZIfNhJUgzL │ │ │ │ ├── _buildManifest.js │ │ │ │ └── _ssgManifest.js │ │ │ │ ├── SqhqgckvG9-Sxn3_Nq2Rt │ │ │ │ ├── _buildManifest.js │ │ │ │ └── _ssgManifest.js │ │ │ │ ├── VZK8jRGqcSpcMf2ZOPpII │ │ │ │ ├── _buildManifest.js │ │ │ │ └── _ssgManifest.js │ │ │ │ ├── Y3oNq6sdVkiLcuMaChJwW │ │ │ │ ├── _buildManifest.js │ │ │ │ └── _ssgManifest.js │ │ │ │ ├── _LnFD6u1WPj3rRxWv1Mp3 │ │ │ │ ├── _buildManifest.js │ │ │ │ └── _ssgManifest.js │ │ │ │ ├── b8NLMEMd7UPwgQ6cqzdXK │ │ │ │ ├── _buildManifest.js │ │ │ │ └── _ssgManifest.js │ │ │ │ ├── chunks │ │ │ │ ├── 07115393-8a796b5d068e3710.js │ │ │ │ ├── 12038df7-bbbca262706a9194.js │ │ │ │ ├── 12038df7-bed05817827b4802.js │ │ │ │ ├── 23-2fc6611658866471.js │ │ │ │ ├── 23-b149ce429217dd65.js │ │ │ │ ├── 39209d7c-1514aaef8caa025b.js │ │ │ │ ├── 39209d7c-9eeaeffa37c8b51e.js │ │ │ │ ├── 39aecf79-474a3d3c48835c08.js │ │ │ │ ├── 39aecf79-8d523cb23043db9d.js │ │ │ │ ├── 472688b4-2c611c3f7f6780f5.js │ │ │ │ ├── 48507feb-c058e15125ba1e58.js │ │ │ │ ├── 48507feb-cb362b7475ba2891.js │ │ │ │ ├── 4f53ad1b-af82feddb1367bb5.js │ │ │ │ ├── 4f53ad1b-cf02b0f93cf25527.js │ │ │ │ ├── 4f9d9cd8-7217d0ac0bfcc7ce.js │ │ │ │ ├── 5349c568-e26f968c6773abca.js │ │ │ │ ├── 737dfa3e-71fd4aa07f7d84a6.js │ │ │ │ ├── 789-e4deefde6e1de3c8.js │ │ │ │ ├── 864-15201e63d2e174b9.js │ │ │ │ ├── 8dc5345f-9a36b2be5ef7459c.js │ │ │ │ ├── 8dc5345f-dfd13b91b6647830.js │ │ │ │ ├── 8e68d877-65c524a5e56473c0.js │ │ │ │ ├── 9081a741-3f102f6aee474fd0.js │ │ │ │ ├── 9081a741-52789bf6b11470c5.js │ │ │ │ ├── 9081a741-560e37099622c351.js │ │ │ │ ├── 9081a741-599fa98ab2a737de.js │ │ │ │ ├── 949-4b7f5a091d97fe2c.js │ │ │ │ ├── app │ │ │ │ │ ├── _not-found │ │ │ │ │ │ ├── page-26d6c07435b6028b.js │ │ │ │ │ │ └── page-aaadc9fa354a98b4.js │ │ │ │ │ ├── layout-ad434663ed5b1d3a.js │ │ │ │ │ ├── page-09caddcec70c8f21.js │ │ │ │ │ ├── page-107cfe4c05eff918.js │ │ │ │ │ ├── page-1afb38c40393046f.js │ │ │ │ │ ├── page-235aaff141d9263e.js │ │ │ │ │ ├── page-25ed1cb73822cf4e.js │ │ │ │ │ ├── page-317294c5dcc5eacf.js │ │ │ │ │ ├── page-345642b96638188b.js │ │ │ │ │ ├── page-3617b8292b21fc34.js │ │ │ │ │ ├── page-45b34f73d34e8979.js │ │ │ │ │ ├── page-54094d73aee6e252.js │ │ │ │ │ ├── page-5e9b74ed5a1be60e.js │ │ │ │ │ ├── page-61a9fa55e8011365.js │ │ │ │ │ ├── page-63c3d501186e1569.js │ │ │ │ │ ├── page-8184afaea67792bd.js │ │ │ │ │ ├── page-a985ad06a3dcc355.js │ │ │ │ │ ├── page-b8f5daf1c95250b5.js │ │ │ │ │ ├── page-c506ad2929c6e6a6.js │ │ │ │ │ ├── page-de101b2b6802134a.js │ │ │ │ │ ├── page-e15dc604b4004fa4.js │ │ │ │ │ ├── page-f3aef3f90382cf14.js │ │ │ │ │ ├── page-f7e98beb8ba64d62.js │ │ │ │ │ └── page-fc144a2905205d63.js │ │ │ │ ├── b536a0f1-cb79989225eaf318.js │ │ │ │ ├── b536a0f1-ea1620b5a816a5f5.js │ │ │ │ ├── bc9c3264-007b030a3d8b973f.js │ │ │ │ ├── ec3863c0-0f36e1c42d4712ac.js │ │ │ │ ├── ec3863c0-3299d7812f924fb2.js │ │ │ │ ├── ec3863c0-666dbee8e5822499.js │ │ │ │ ├── ec3863c0-b59cee7fa657bb4d.js │ │ │ │ ├── fd9d1056-3c0a5e4377f054b9.js │ │ │ │ ├── fd9d1056-5afc1fda0426cd7c.js │ │ │ │ ├── framework-00a8ba1a63cfdc9e.js │ │ │ │ ├── main-0806fb9f50640b69.js │ │ │ │ ├── main-app-6d8fe3bc29305481.js │ │ │ │ ├── pages │ │ │ │ │ ├── _app-037b5d058bd9a820.js │ │ │ │ │ └── _error-6ae619510b1539d6.js │ │ │ │ ├── polyfills-78c92fac7aa8fdd8.js │ │ │ │ └── webpack-e6d8fc8882b3cc5a.js │ │ │ │ ├── cpNG_krRh40F8ypWaUA1Y │ │ │ │ ├── _buildManifest.js │ │ │ │ └── _ssgManifest.js │ │ │ │ ├── css │ │ │ │ ├── 0ffc59f004ebeefe.css │ │ │ │ ├── 2817a3d3bb800805.css │ │ │ │ ├── ae5cf92d392439f8.css │ │ │ │ ├── b219313ebc6bfc74.css │ │ │ │ ├── b6698fd034c37467.css │ │ │ │ ├── b7332ce1649563ef.css │ │ │ │ ├── bbb58f872eab5c8f.css │ │ │ │ ├── d919237d8b9336c0.css │ │ │ │ └── fb11073f70ca561d.css │ │ │ │ ├── gjEH1UGrJtEx0lJhUhCoG │ │ │ │ ├── _buildManifest.js │ │ │ │ └── _ssgManifest.js │ │ │ │ ├── ifjjNsXVlVkzB0f2yWOlr │ │ │ │ ├── _buildManifest.js │ │ │ │ └── _ssgManifest.js │ │ │ │ ├── loIKTVc-LZ1tLrqnZ0_At │ │ │ │ ├── _buildManifest.js │ │ │ │ └── _ssgManifest.js │ │ │ │ ├── media │ │ │ │ ├── 034043092db1e233-s.woff2 │ │ │ │ ├── 062522b8b7c3ad6a-s.woff2 │ │ │ │ ├── 19e37deead9b3ec2-s.woff2 │ │ │ │ ├── 26a46d62cd723877-s.woff2 │ │ │ │ ├── 2b3f1035ed87a788-s.p.woff2 │ │ │ │ ├── 3d9ea938b6afa941-s.p.woff2 │ │ │ │ ├── 4049f3f580e14086-s.p.woff2 │ │ │ │ ├── 46392699924ae7e5-s.woff2 │ │ │ │ ├── 55c55f0601d81cf3-s.woff2 │ │ │ │ ├── 581909926a08bbc8-s.woff2 │ │ │ │ ├── 65053818c3abcf97-s.woff2 │ │ │ │ ├── 6d93bde91c0c2823-s.woff2 │ │ │ │ ├── 6fed4e5749a3ea15-s.woff2 │ │ │ │ ├── 83651bee47cf14da-s.woff2 │ │ │ │ ├── 84a5d21698cdcea6-s.woff2 │ │ │ │ ├── 97e0cb1ae144a2a9-s.woff2 │ │ │ │ ├── 9beef36ab83de3f0-s.woff2 │ │ │ │ ├── a1471ccaedd577d0-s.woff2 │ │ │ │ ├── a34f9d1faa5f3315-s.p.woff2 │ │ │ │ ├── dd4ab5b525bd804a-s.woff2 │ │ │ │ ├── df0a9ae256c0569c-s.woff2 │ │ │ │ ├── df5e9368d28a76aa-s.woff2 │ │ │ │ ├── e6f5886ae1242622-s.woff2 │ │ │ │ ├── eed6db14ac3b93a0-s.woff2 │ │ │ │ └── faac4ac11aa3d97b-s.woff2 │ │ │ │ ├── pR7o7Axy7wuvopYTQQ4gp │ │ │ │ ├── _buildManifest.js │ │ │ │ └── _ssgManifest.js │ │ │ │ ├── ppWjoMOwBDfvgLeNC4RNs │ │ │ │ ├── _buildManifest.js │ │ │ │ └── _ssgManifest.js │ │ │ │ ├── sJVEctNLIfCe2KAU81egg │ │ │ │ ├── _buildManifest.js │ │ │ │ └── _ssgManifest.js │ │ │ │ ├── tVocASfF6DGpJwQWyOdO9 │ │ │ │ ├── _buildManifest.js │ │ │ │ └── _ssgManifest.js │ │ │ │ └── yPC90wje_7V701wv-Jubb │ │ │ │ ├── _buildManifest.js │ │ │ │ └── _ssgManifest.js │ │ │ ├── alps_field_1k.hdr │ │ │ ├── cloudy.hdr │ │ │ ├── cool_cap.png │ │ │ ├── fire_cap.png │ │ │ ├── gold_matcap.png │ │ │ ├── golden_cap.png │ │ │ ├── ice_cap.png │ │ │ ├── icon.ico │ │ │ ├── index.html │ │ │ ├── index.txt │ │ │ ├── macbook.gltf │ │ │ ├── next.svg │ │ │ ├── shaders │ │ │ ├── includes │ │ │ │ └── simplexNoise4d.glsl │ │ │ └── wobble │ │ │ │ ├── fragment.glsl │ │ │ │ └── vertex.glsl │ │ │ ├── shiny_cap.png │ │ │ ├── silver_cap.png │ │ │ ├── verba.glb │ │ │ ├── verba.gltf │ │ │ ├── verba.png │ │ │ ├── vercel.svg │ │ │ ├── weaviate.glb │ │ │ └── weaviate.png │ ├── helpers.py │ └── types.py ├── tests │ └── document │ │ └── test_document.py └── verba_manager.py ├── img ├── api_screen.png ├── ollama_running.png ├── thumbnail.png ├── verba.gif ├── verba_architecture.png ├── verba_data.png ├── verba_deployment.png ├── verba_icon.png ├── verba_rag.png ├── verba_screen.png ├── verba_select_embedder.png └── verba_status.png ├── pypi_commands.sh └── setup.py /.github/ISSUE_TEMPLATE/verba-feature-template.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Verba Feature Template 3 | about: Request a new feature for Verba 4 | title: "" 5 | labels: "enhancement" 6 | assignees: "" 7 | --- 8 | 9 | ## Description 10 | 11 | 12 | 13 | ## Additional context 14 | 15 | 16 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/verba-issue-template.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Verba Issue Template 3 | about: Encountering errors or issues with Verba 4 | title: "" 5 | labels: "" 6 | assignees: "" 7 | --- 8 | 9 | ## Description 10 | 11 | 12 | 13 | ## Installation 14 | 15 | 16 | 17 | - [ ] pip install goldenverba 18 | - [ ] pip install from source 19 | - [ ] Docker installation 20 | 21 | If you installed via pip, please specify the version: 22 | 23 | ## Weaviate Deployment 24 | 25 | 26 | 27 | - [ ] Local Deployment 28 | - [ ] Docker Deployment 29 | - [ ] Cloud Deployment 30 | 31 | ## Configuration 32 | 33 | 34 | 35 | Reader: 36 | Chunker: 37 | Embedder: 38 | Retriever: 39 | Generator: 40 | 41 | ## Steps to Reproduce 42 | 43 | 44 | 45 | ## Additional context 46 | 47 | 48 | -------------------------------------------------------------------------------- /.github/workflows/docker-image.yml: -------------------------------------------------------------------------------- 1 | name: Docker Build and Push 2 | 3 | on: 4 | push: 5 | branches: ["main"] 6 | 7 | jobs: 8 | build-and-push: 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - name: Checkout code 13 | uses: actions/checkout@v4 14 | 15 | - name: Set up Docker Buildx 16 | uses: docker/setup-buildx-action@v3 17 | 18 | - name: Login to DockerHub 19 | uses: docker/login-action@v3 20 | with: 21 | username: ${{secrets.DOCKER_USERNAME}} 22 | password: ${{secrets.DOCKER_PASSWORD}} 23 | 24 | - name: Build and push 25 | uses: docker/build-push-action@v4 26 | with: 27 | context: . 28 | file: ./Dockerfile 29 | push: true 30 | tags: semitechnologies/verba:latest 31 | platforms: linux/amd64,linux/arm64 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | .env* 3 | __pycache__ 4 | .DS_Store 5 | .pytest_cache 6 | .python-version 7 | *.egg-info 8 | venv 9 | venv* 10 | dist 11 | build 12 | ~ 13 | .local 14 | .cache 15 | .verba 16 | .vscode 17 | verba_config.json 18 | text-generation-inference 19 | test.py 20 | cache.txt 21 | .ruff_cache 22 | *_secrets.json 23 | ollama 24 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Verba Contribution Guidelines 2 | 3 | Welcome to the Verba community! We're thrilled that you're interested in contributing to the Verba project. Verba is a collaborative open-source project, and we believe that everyone has something unique to contribute. Below you'll find our guidelines which aim to make contributing to Verba a respectful and pleasant experience for everyone. 4 | 5 | ## 🌟 Community and Open Source 6 | 7 | Open source is at the heart of Verba. We appreciate feedback, ideas, and enhancements from the community. Whether you're looking to fix a bug, add a new feature, or simply improve the documentation, your contribution is important to us. 8 | 9 | ## 📚 Before You Begin 10 | 11 | Before contributing, please take a moment to read through the [README](https://github.com/weaviate/Verba/README.md) and the [Technical Documentation](https://github.com/weaviate/Verba/TECHNICAL.md). These documents provide a comprehensive understanding of the project and are essential reading to ensure that we're all on the same page. Please note that the technical documentation is a work in progress and will be updated as we progress. 12 | 13 | ## 🐛 Reporting Issues 14 | 15 | If you've identified a bug or have an idea for an enhancement, please begin by creating an Issue. Here's how: 16 | 17 | - Check the Issue tracker to ensure the bug or enhancement hasn't already been reported. 18 | - Clearly describe the issue including steps to reproduce when it is a bug. 19 | - Include as much relevant information as possible. 20 | 21 | ## 💡 Ideas and Feedback 22 | 23 | We welcome all ideas and feedback. If you're not ready to open an Issue or if you're just looking for a place to discuss ideas, head over to our [GitHub Discussions](https://github.com/weaviate/Verba/discussions) or the [Weaviate Support Page](https://forum.weaviate.io/). 24 | 25 | ## 🧪 Testing 26 | 27 | We use [pytest](https://docs.pytest.org) for testing. Please note that the tests are WIP and some are missing. We still encourage you to run the tests and add more tests as you see fit. 28 | 29 | To run the tests, use the following command: 30 | 31 | ```bash 32 | pytest goldenverba/tests 33 | ``` 34 | 35 | ## 📝 Pull Requests 36 | 37 | If you're ready to contribute code or documentation, please submit a Pull Request (PR) to the dev branch. Here's the process: 38 | 39 | - Fork the repository and create your branch from `main`. 40 | - Ensure that your code adheres to the existing code style. Use [Black](https://github.com/psf/black) for formatting Python code. 41 | - If you're adding a new feature, consider writing unit tests and documenting the feature. 42 | - Verify that your changes pass existing unit tests 43 | - Make sure your code lints (mypy compatibility is optional but encouraged). 44 | - Include a clear description of your changes in the PR. 45 | - Link to the Issue in your PR description. 46 | 47 | ### 🔄 Pull Request Process 48 | 49 | - PRs are reviewed on a regular basis. 50 | - Engage in the conversation and make requested updates to your PR if needed. 51 | - Once approved, your PR will be merged into the main branch by a maintainer. 52 | 53 | ## 🗨️ Stay Connected 54 | 55 | We encourage you to join our community channels. Stay connected, share ideas, and get to know fellow contributors. 56 | 57 | Thank you for being a part of Verba. Your contributions not only help improve the project but also the wider community of users and developers. 58 | 59 | Happy contributing! 60 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.11 2 | WORKDIR /Verba 3 | COPY . /Verba 4 | RUN pip install '.' 5 | EXPOSE 8000 6 | CMD ["verba", "start","--port","8000","--host","0.0.0.0"] 7 | -------------------------------------------------------------------------------- /FRONTEND.md: -------------------------------------------------------------------------------- 1 | # Verba - Frontend Documentation 2 | 3 | Verba's Frontend is a [NextJS](https://nextjs.org/) application used together with [TailwindCSS](https://tailwindcss.com/) and [DaisyUI](https://daisyui.com/). 4 | 5 | ## 🚀 Setting Up the Frontend 6 | 7 | To get your local copy of the Verba frontend up and running, please follow these simple steps: 8 | 9 | 1. Clone Repository 10 | 11 | ```git 12 | 13 | git clone https://github.com/weaviate/Verba.git 14 | 15 | ``` 16 | 17 | 1. **Node.js Requirement**: 18 | 19 | - Confirm that Node.js version `>=21.3.0` is installed on your system. If you need to install or update Node.js, visit the official [Node.js website](https://nodejs.org/). 20 | 21 | 2. **Installation**: 22 | 23 | - Navigate to the frontend directory: `cd frontend` 24 | - Run `npm install` to install the dependencies required for the project. 25 | 26 | 3. **Development Server**: 27 | - Launch the application in development mode by executing `npm run dev`. 28 | - Open your web browser and visit `http://localhost:3000` to view the application. 29 | 30 | ## 📦 Building Static Pages for FastAPI 31 | 32 | If you wish to serve and update the frontend through FastAPI, you need to build static pages: 33 | 34 | 1. **Build Process**: 35 | - Execute `npm run build` to generate the static production build. The output will be directed to the FastAPI folder configured to serve the static content. 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020-2023, Weaviate B.V. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-include goldenverba/server/frontend/out * -------------------------------------------------------------------------------- /PYTHON_TUTORIAL.md: -------------------------------------------------------------------------------- 1 | # Installing Python and Setting Up a Virtual Environment 2 | 3 | Before you can use Verba, you'll need to ensure that `Python >=3.10.0` is installed on your system and that you can create a virtual environment for a safer and cleaner project setup. 4 | 5 | ## Installing Python 6 | 7 | Python is required to run Verba. If you don't have Python installed, follow these steps: 8 | 9 | ### For Windows: 10 | 11 | Download the latest Python installer from the official Python website. 12 | Run the installer and make sure to check the box that says `Add Python to PATH` during installation. 13 | 14 | ### For macOS: 15 | 16 | You can install Python using Homebrew, a package manager for macOS, with the following command in the terminal: 17 | 18 | ``` 19 | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 20 | ``` 21 | 22 | Then install Python: 23 | 24 | ``` 25 | brew install python 26 | ``` 27 | 28 | ### For Linux: 29 | 30 | Python usually comes pre-installed on most Linux distributions. If it's not, you can install it using your distribution's package manager. You can read more about it [here](https://opensource.com/article/20/4/install-python-linux) 31 | 32 | ## Setting Up a Virtual Environment 33 | 34 | It's recommended to use a virtual environment to avoid conflicts with other projects or system-wide Python packages. 35 | 36 | ### Install the virtualenv package: 37 | 38 | First, ensure you have pip installed (it comes with Python if you're using version 3.4 and above). 39 | Install virtualenv by running: 40 | 41 | ``` 42 | pip install virtualenv 43 | ``` 44 | 45 | ### Create a Virtual Environment: 46 | 47 | Navigate to your project's directory in the terminal. 48 | Run the following command to create a virtual environment named venv (you can name it anything you like): 49 | 50 | ``` 51 | python3 -m virtualenv venv 52 | ``` 53 | 54 | ### Activate the Virtual Environment: 55 | 56 | - On Windows, activate the virtual environment by running: 57 | 58 | ``` 59 | venv\Scripts\activate.bat 60 | ``` 61 | 62 | - On macOS and Linux, activate it with: 63 | 64 | ``` 65 | source venv/bin/activate 66 | ``` 67 | 68 | Once your virtual environment is activated, you'll see its name in the terminal prompt. Now you're ready to install Verba using the steps provided in the Quickstart sections. 69 | 70 | > Remember to deactivate the virtual environment when you're done working with Verba by simply running deactivate in the terminal. 71 | -------------------------------------------------------------------------------- /TECHNICAL.md: -------------------------------------------------------------------------------- 1 | # Verba - Technical Documentation 2 | 3 | This technical documentation is intended for developers who want to understand the inner workings of Verba. Please note that this document might be uncomplete and missing some parts. If you encounter any issues or have questions, please feel free to open an issue. 4 | 5 | ## FastAPI Server 6 | 7 | Verba is served through a FastAPI server. The server is serving the static frontend files through the specified port. If you're modifying the frontend, you will need to rebuild the static files again. The frontend is sending API calls to itself which the FastAPI server handles. The server can handle multiple client connections which are handled by the `ClientManager` class. 8 | 9 | ### ClientManager 10 | 11 | `TODO` 12 | 13 | For handling large upload of files, the `BatchManager` class handles batches of data of a single file to merge it into a single file once all batches have been received. 14 | 15 | ### BatchManager 16 | 17 | `TODO` 18 | 19 | ### Websocket 20 | 21 | `TODO` 22 | 23 | ## Automated Testing 24 | 25 | `TODO` 26 | 27 | ## FAQ 28 | 29 | ### How to control the position of context sent to the Generator to generate a response? 30 | 31 | Every `generator` class has a `prepare_messages` method. This method is used to format the messages that are sent to the LLM. The position of the context in the messages is important because it determines where the context is placed in the conversation. 32 | 33 | ### How to upload a JSON file to Verba? 34 | 35 | ## Verba JSON Structure 36 | 37 | A Verba Document can be created from a JSON object. The JSON object is converted to a Verba Document object and then uploaded to the vector database. Here's the general structure of a Verba Document (you can also find the implementation in the `Document.py` file): 38 | 39 | ```python 40 | { 41 | "title": "string", # The title of the document 42 | "content": "string", # The content of the document 43 | "extension": "string", # The extension of the document (Optional) 44 | "fileSize": "number", # The size of the document in bytes (Optional) 45 | "labels": "array", # The labels of the document (can be empty, used for filtering) 46 | "source": "string", # The source of the document (can be an URL, optional) 47 | "meta": "object", # The meta data of the document used internally 48 | "metadata": "string" # Metadata information of the document, will be used in the embedding process 49 | } 50 | ``` 51 | 52 | ## Custom JSON Structure 53 | 54 | There is currently no support for custom JSON structure. Instead the whole JSON will simply be dumped into the content field of the Verba document. 55 | There are plans to add support for custom JSON structure in the future. 56 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | services: 4 | verba: 5 | build: 6 | context: ./ 7 | dockerfile: Dockerfile 8 | ports: 9 | - 8000:8000 10 | environment: 11 | - WEAVIATE_URL_VERBA=http://weaviate:8080 12 | - OPENAI_API_KEY=$OPENAI_API_KEY 13 | - COHERE_API_KEY=$COHERE_API_KEY 14 | - OLLAMA_URL=http://host.docker.internal:11434 15 | - OLLAMA_MODEL=$OLLAMA_MODEL 16 | - OLLAMA_EMBED_MODEL=$OLLAMA_EMBED_MODEL 17 | - UNSTRUCTURED_API_KEY=$UNSTRUCTURED_API_KEY 18 | - UNSTRUCTURED_API_URL=$UNSTRUCTURED_API_URL 19 | - GITHUB_TOKEN=$GITHUB_TOKEN 20 | 21 | volumes: 22 | - ./data:/data/ 23 | depends_on: 24 | weaviate: 25 | condition: service_healthy 26 | healthcheck: 27 | test: wget --no-verbose --tries=3 --spider http://localhost:8000 || exit 1 28 | interval: 5s 29 | timeout: 10s 30 | retries: 5 31 | start_period: 10s 32 | networks: 33 | - ollama-docker 34 | 35 | weaviate: 36 | command: 37 | - --host 38 | - 0.0.0.0 39 | - --port 40 | - '8080' 41 | - --scheme 42 | - http 43 | image: semitechnologies/weaviate:1.25.10 44 | ports: 45 | - 8080:8080 46 | - 3000:8080 47 | volumes: 48 | - weaviate_data:/var/lib/weaviate 49 | restart: on-failure:0 50 | healthcheck: 51 | test: wget --no-verbose --tries=3 --spider http://localhost:8080/v1/.well-known/ready || exit 1 52 | interval: 5s 53 | timeout: 10s 54 | retries: 5 55 | start_period: 10s 56 | environment: 57 | OPENAI_APIKEY: $OPENAI_API_KEY 58 | COHERE_APIKEY: $COHERE_API_KEY 59 | QUERY_DEFAULTS_LIMIT: 25 60 | AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: 'true' 61 | PERSISTENCE_DATA_PATH: '/var/lib/weaviate' 62 | ENABLE_MODULES: 'e' 63 | CLUSTER_HOSTNAME: 'node1' 64 | networks: 65 | - ollama-docker 66 | 67 | # Uncomment to use Ollama within the same docker compose 68 | 69 | # ollama: 70 | # image: ollama/ollama:latest 71 | # ports: 72 | # - 7869:11434 73 | # volumes: 74 | # - .:/code 75 | # - ./ollama/ollama:/root/.ollama 76 | # container_name: ollama 77 | # pull_policy: always 78 | # tty: true 79 | # restart: always 80 | # environment: 81 | # - OLLAMA_KEEP_ALIVE=24h 82 | # - OLLAMA_HOST=0.0.0.0 83 | # networks: 84 | # - ollama-docker 85 | 86 | volumes: 87 | weaviate_data: {} 88 | 89 | 90 | networks: 91 | ollama-docker: 92 | external: false 93 | 94 | ... -------------------------------------------------------------------------------- /frontend/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /frontend/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env*.local 29 | 30 | # vercel 31 | .vercel 32 | 33 | # typescript 34 | *.tsbuildinfo 35 | next-env.d.ts 36 | -------------------------------------------------------------------------------- /frontend/app/components/Chat/ChatView.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import React, { useState } from "react"; 4 | import ChatInterface from "./ChatInterface"; 5 | 6 | import DocumentExplorer from "../Document/DocumentExplorer"; 7 | 8 | import { 9 | Credentials, 10 | RAGConfig, 11 | ChunkScore, 12 | Theme, 13 | DocumentFilter, 14 | } from "@/app/types"; 15 | 16 | interface ChatViewProps { 17 | selectedTheme: Theme; 18 | credentials: Credentials; 19 | addStatusMessage: ( 20 | message: string, 21 | type: "INFO" | "WARNING" | "SUCCESS" | "ERROR" 22 | ) => void; 23 | production: "Local" | "Demo" | "Production"; 24 | currentPage: string; 25 | RAGConfig: RAGConfig | null; 26 | setRAGConfig: React.Dispatch>; 27 | documentFilter: DocumentFilter[]; 28 | setDocumentFilter: React.Dispatch>; 29 | } 30 | 31 | const ChatView: React.FC = ({ 32 | credentials, 33 | selectedTheme, 34 | addStatusMessage, 35 | production, 36 | currentPage, 37 | RAGConfig, 38 | setRAGConfig, 39 | documentFilter, 40 | setDocumentFilter, 41 | }) => { 42 | const [selectedDocument, setSelectedDocument] = useState(null); 43 | const [selectedChunkScore, setSelectedChunkScore] = useState( 44 | [] 45 | ); 46 | return ( 47 |
48 |
51 | 64 |
65 | 66 |
69 | 80 |
81 |
82 | ); 83 | }; 84 | 85 | export default ChatView; 86 | -------------------------------------------------------------------------------- /frontend/app/components/Chat/StatusLabel.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import React from "react"; 4 | 5 | interface StatusLabelProps { 6 | status: boolean; 7 | true_text: string; 8 | false_text: string; 9 | } 10 | 11 | const StatusLabel: React.FC = ({ 12 | status, 13 | true_text, 14 | false_text, 15 | }) => { 16 | return ( 17 |
20 |

23 | {status ? true_text : false_text} 24 |

25 |
26 | ); 27 | }; 28 | 29 | export default StatusLabel; 30 | -------------------------------------------------------------------------------- /frontend/app/components/Document/DocumentMetaView.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import React, { useState, useEffect } from "react"; 4 | import { VerbaDocument, Credentials } from "@/app/types"; 5 | import { fetchSelectedDocument } from "@/app/api"; 6 | 7 | interface DocumentMetaViewProps { 8 | selectedDocument: string; 9 | credentials: Credentials; 10 | } 11 | 12 | const DocumentMetaView: React.FC = ({ 13 | selectedDocument, 14 | credentials, 15 | }) => { 16 | const [isFetching, setIsFetching] = useState(true); 17 | const [document, setDocument] = useState(null); 18 | 19 | useEffect(() => { 20 | handleFetchDocument(); 21 | }, [selectedDocument]); 22 | 23 | const handleFetchDocument = async () => { 24 | try { 25 | setIsFetching(true); 26 | 27 | const data = await fetchSelectedDocument(selectedDocument, credentials); 28 | 29 | if (data) { 30 | if (data.error !== "") { 31 | setDocument(null); 32 | setIsFetching(false); 33 | } else { 34 | setDocument(data.document); 35 | setIsFetching(false); 36 | } 37 | } 38 | } catch (error) { 39 | console.error("Failed to fetch document:", error); 40 | setIsFetching(false); 41 | } 42 | }; 43 | 44 | return ( 45 |
46 | {isFetching ? ( 47 |
48 | 49 |
50 | ) : ( 51 | document && ( 52 |
53 |
54 |

55 | Title 56 |

57 |

61 | {document.title} 62 |

63 |
64 |
65 |

66 | Metadata 67 |

68 |

{document.metadata}

69 |
70 |
71 |

72 | Extension 73 |

74 |

{document.extension}

75 |
76 |
77 |

78 | File Size 79 |

80 |

{document.fileSize}

81 |
82 |
83 |

84 | Source 85 |

86 | 93 |
94 |
95 |

96 | Labels 97 |

98 |

{document.labels}

99 |
100 |
101 | ) 102 | )} 103 |
104 | ); 105 | }; 106 | 107 | export default DocumentMetaView; 108 | -------------------------------------------------------------------------------- /frontend/app/components/Document/DocumentView.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import React, { useState } from "react"; 4 | import DocumentSearch from "./DocumentSearch"; 5 | import DocumentExplorer from "./DocumentExplorer"; 6 | import { Credentials, Theme, DocumentFilter } from "@/app/types"; 7 | 8 | interface DocumentViewProps { 9 | selectedTheme: Theme; 10 | production: "Local" | "Demo" | "Production"; 11 | credentials: Credentials; 12 | documentFilter: DocumentFilter[]; 13 | setDocumentFilter: React.Dispatch>; 14 | addStatusMessage: ( 15 | message: string, 16 | type: "INFO" | "WARNING" | "SUCCESS" | "ERROR" 17 | ) => void; 18 | } 19 | 20 | const DocumentView: React.FC = ({ 21 | selectedTheme, 22 | production, 23 | credentials, 24 | documentFilter, 25 | setDocumentFilter, 26 | addStatusMessage, 27 | }) => { 28 | const [selectedDocument, setSelectedDocument] = useState(null); 29 | 30 | return ( 31 |
32 |
35 | 42 |
43 | 44 |
47 | 57 |
58 |
59 | ); 60 | }; 61 | 62 | export default DocumentView; 63 | -------------------------------------------------------------------------------- /frontend/app/components/Ingestion/FileComponent.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import React from "react"; 4 | import { FileData, FileMap, statusTextMap } from "@/app/types"; 5 | import { FaTrash } from "react-icons/fa"; 6 | import { FaCheckCircle } from "react-icons/fa"; 7 | import { MdError } from "react-icons/md"; 8 | 9 | import UserModalComponent from "../Navigation/UserModal"; 10 | 11 | import VerbaButton from "../Navigation/VerbaButton"; 12 | 13 | interface FileComponentProps { 14 | fileData: FileData; 15 | fileMap: FileMap; 16 | handleDeleteFile: (name: string) => void; 17 | selectedFileData: string | null; 18 | setSelectedFileData: (f: string | null) => void; 19 | } 20 | 21 | const FileComponent: React.FC = ({ 22 | fileData, 23 | fileMap, 24 | handleDeleteFile, 25 | selectedFileData, 26 | setSelectedFileData, 27 | }) => { 28 | const openDeleteModal = () => { 29 | const modal = document.getElementById( 30 | "remove_file_" + fileMap[fileData.fileID].filename 31 | ); 32 | if (modal instanceof HTMLDialogElement) { 33 | modal.showModal(); 34 | } 35 | }; 36 | 37 | return ( 38 |
39 | {fileMap[fileData.fileID].status != "READY" ? ( 40 |
41 | {fileMap[fileData.fileID].status != "DONE" && 42 | fileMap[fileData.fileID].status != "ERROR" && ( 43 | 47 | )} 48 | {fileMap[fileData.fileID].status == "DONE" && ( 49 | 56 | )} 57 | {fileMap[fileData.fileID].status == "ERROR" && ( 58 | 65 | )} 66 |
67 | ) : ( 68 |
69 | 74 |
75 | )} 76 | 77 | { 88 | setSelectedFileData(fileData.fileID); 89 | }} 90 | /> 91 | 92 | 99 | 100 | 114 |
115 | ); 116 | }; 117 | 118 | export default FileComponent; 119 | -------------------------------------------------------------------------------- /frontend/app/components/Navigation/InfoComponent.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import React, { useState } from "react"; 4 | import { FaInfo } from "react-icons/fa"; 5 | import VerbaButton from "./VerbaButton"; 6 | 7 | interface InfoComponentProps { 8 | tooltip_text: string; 9 | display_text: string; 10 | } 11 | 12 | const InfoComponent: React.FC = ({ 13 | tooltip_text, 14 | display_text, 15 | }) => { 16 | const [showTooltip, setShowTooltip] = useState(false); 17 | 18 | return ( 19 |
20 |
setShowTooltip(true)} 22 | onMouseLeave={() => setShowTooltip(false)} 23 | className="relative cursor-pointer flex flex-col items-center text-text-alt-verba" 24 | > 25 |

{display_text}

26 |
31 |

{tooltip_text}

32 |
33 |
34 |
35 | ); 36 | }; 37 | 38 | export default InfoComponent; 39 | -------------------------------------------------------------------------------- /frontend/app/components/Navigation/NavButton.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import React from "react"; 4 | import { FaStar } from "react-icons/fa"; 5 | import VerbaButton from "./VerbaButton"; 6 | 7 | interface NavbarButtonProps { 8 | Icon: typeof FaStar; 9 | title: string; 10 | currentPage: string; 11 | setCurrentPage: ( 12 | page: "CHAT" | "DOCUMENTS" | "STATUS" | "ADD" | "SETTINGS" | "RAG" 13 | ) => void; 14 | setPage: "CHAT" | "DOCUMENTS" | "STATUS" | "ADD" | "SETTINGS" | "RAG"; 15 | hide: boolean; 16 | } 17 | 18 | const NavbarButton: React.FC = ({ 19 | Icon, 20 | title, 21 | currentPage, 22 | setPage, 23 | setCurrentPage, 24 | hide, 25 | }) => { 26 | return ( 27 | { 33 | setCurrentPage(setPage); 34 | }} 35 | disabled={hide} 36 | /> 37 | ); 38 | }; 39 | 40 | export default NavbarButton; 41 | -------------------------------------------------------------------------------- /frontend/app/components/Navigation/StatusMessenger.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import React, { useState, useEffect } from "react"; 4 | import { StatusMessage } from "@/app/types"; 5 | import { motion, AnimatePresence } from "framer-motion"; 6 | 7 | import { FaWandMagicSparkles } from "react-icons/fa6"; 8 | import { IoWarning } from "react-icons/io5"; 9 | import { BiSolidMessageAltDetail } from "react-icons/bi"; 10 | import { BiSolidErrorCircle } from "react-icons/bi"; 11 | 12 | interface StatusMessengerProps { 13 | status_messages: StatusMessage[]; 14 | set_status_messages: (messages: StatusMessage[]) => void; 15 | } 16 | 17 | const StatusMessengerComponent: React.FC = ({ 18 | status_messages, 19 | set_status_messages, 20 | }) => { 21 | const [messages, setMessages] = useState([]); 22 | 23 | useEffect(() => { 24 | if (status_messages.length > 0) { 25 | // Add new messages to the state 26 | setMessages((prevMessages) => [...prevMessages, ...status_messages]); 27 | 28 | // Clear the status_messages 29 | set_status_messages([]); 30 | } 31 | 32 | // Clear messages older than 5 seconds 33 | const interval = setInterval(() => { 34 | const currentTime = new Date().getTime(); 35 | setMessages((prevMessages) => 36 | prevMessages.filter((message) => { 37 | const messageTime = new Date(message.timestamp).getTime(); 38 | return currentTime - messageTime < 5000; 39 | }) 40 | ); 41 | }, 1000); // Check every second 42 | 43 | return () => clearInterval(interval); 44 | }, [status_messages, set_status_messages]); 45 | 46 | const getMessageColor = (type: string) => { 47 | switch (type) { 48 | case "INFO": 49 | return "bg-button-verba"; 50 | case "WARNING": 51 | return "bg-secondary-verba"; 52 | case "SUCCESS": 53 | return "bg-primary-verba"; 54 | case "ERROR": 55 | return "bg-warning-verba"; 56 | default: 57 | return "bg-button-verba"; 58 | } 59 | }; 60 | 61 | const getMessageIcon = (type: string) => { 62 | const icon_size = 15; 63 | 64 | switch (type) { 65 | case "INFO": 66 | return ; 67 | case "WARNING": 68 | return ; 69 | case "SUCCESS": 70 | return ; 71 | case "ERROR": 72 | return ; 73 | default: 74 | return ; 75 | } 76 | }; 77 | 78 | return ( 79 |
80 | 81 | {messages 82 | .filter((message) => { 83 | const messageTime = new Date(message.timestamp).getTime(); 84 | const currentTime = new Date().getTime(); 85 | return currentTime - messageTime < 5000; // 5 seconds in milliseconds 86 | }) 87 | .map((message, index) => ( 88 | 95 |
96 |
97 | {getMessageIcon(message.type)} 98 |

{message.type}

99 |
100 |

{message.message}

101 |
102 |
103 | ))} 104 |
105 |
106 | ); 107 | }; 108 | 109 | export default StatusMessengerComponent; 110 | -------------------------------------------------------------------------------- /frontend/app/components/Navigation/UserModal.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import React from "react"; 4 | 5 | interface UserModalComponentProps { 6 | modal_id: string; 7 | title: string; 8 | text: string; 9 | triggerAccept?: null | ((a: any) => void); 10 | triggerValue?: any | null; 11 | triggerString?: string | null; 12 | } 13 | 14 | import VerbaButton from "./VerbaButton"; 15 | 16 | const UserModalComponent: React.FC = ({ 17 | title, 18 | modal_id, 19 | text, 20 | triggerAccept, 21 | triggerString, 22 | triggerValue, 23 | }) => { 24 | return ( 25 | 26 |
27 |

{title}

28 |

{text}

29 |
30 |
31 | {triggerAccept && triggerString && ( 32 | { 36 | triggerAccept(triggerValue); 37 | }} 38 | /> 39 | )} 40 | 46 | 47 |
48 |
49 |
50 | ); 51 | }; 52 | 53 | export default UserModalComponent; 54 | -------------------------------------------------------------------------------- /frontend/app/components/Navigation/VerbaButton.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import React from "react"; 4 | import { FaStar } from "react-icons/fa"; 5 | 6 | interface VerbaButtonProps { 7 | title?: string; 8 | Icon?: typeof FaStar; 9 | onClick?: (...args: any[]) => void; // Updated to accept any number of arguments 10 | onMouseEnter?: (...args: any[]) => void; 11 | onMouseLeave?: (...args: any[]) => void; 12 | disabled?: boolean; 13 | key?: string; 14 | className?: string; 15 | type?: "button" | "submit" | "reset"; 16 | selected?: boolean; 17 | selected_color?: string; 18 | selected_text_color?: string; 19 | circle?: boolean; 20 | text_class_name?: string; 21 | loading?: boolean; 22 | text_size?: string; 23 | icon_size?: number; 24 | onClickParams?: any[]; // New prop to pass additional parameters 25 | } 26 | 27 | const VerbaButton: React.FC = ({ 28 | title = "", 29 | key = "Button" + title, 30 | Icon, 31 | onClick = () => {}, 32 | onMouseEnter = () => {}, 33 | onMouseLeave = () => {}, 34 | disabled = false, 35 | className = "", 36 | text_class_name = "", 37 | selected = false, 38 | selected_color = "bg-button-verba", 39 | selected_text_color = "text-text-verba-button", 40 | text_size = "text-xs", 41 | icon_size = 12, 42 | type = "button", 43 | loading = false, 44 | circle = false, 45 | onClickParams = [], 46 | }) => { 47 | return ( 48 | 73 | ); 74 | }; 75 | 76 | export default VerbaButton; 77 | -------------------------------------------------------------------------------- /frontend/app/components/Navigation/util.ts: -------------------------------------------------------------------------------- 1 | export async function getGitHubStars(): Promise { 2 | try { 3 | const response: any = await fetch( 4 | "https://api.github.com/repos/weaviate/verba", 5 | { 6 | method: "GET", 7 | } 8 | ); 9 | 10 | const data: any = await response.json(); 11 | 12 | if (data) { 13 | return data.stargazers_count; 14 | } else { 15 | return 0; 16 | } 17 | } catch (error) { 18 | console.error("Failed to perform search:", error); 19 | return 0; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /frontend/app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | .react-colorful { 6 | height: 100px; 7 | } 8 | -------------------------------------------------------------------------------- /frontend/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from "next"; 2 | import "./globals.css"; 3 | 4 | export const metadata: Metadata = { 5 | title: "Verba", 6 | description: "The GoldenRAGtriever", 7 | }; 8 | 9 | export default function RootLayout({ 10 | children, 11 | }: Readonly<{ 12 | children: React.ReactNode; 13 | }>) { 14 | return ( 15 | 16 | 17 | 18 | {children} 19 | 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /frontend/app/util.ts: -------------------------------------------------------------------------------- 1 | import { Inter, Plus_Jakarta_Sans, Open_Sans, PT_Mono } from "next/font/google"; 2 | import { RAGConfig } from "./types"; 3 | 4 | // Fonts 5 | const inter = Inter({ subsets: ["latin"] }); 6 | const plus_jakarta_sans = Plus_Jakarta_Sans({ subsets: ["latin"] }); 7 | const open_sans = Open_Sans({ subsets: ["latin"] }); 8 | const pt_mono = PT_Mono({ subsets: ["latin"], weight: "400" }); 9 | export type FontKey = "Inter" | "Plus_Jakarta_Sans" | "Open_Sans" | "PT_Mono"; 10 | 11 | export const fonts: Record = { 12 | Inter: inter, 13 | Plus_Jakarta_Sans: plus_jakarta_sans, 14 | Open_Sans: open_sans, 15 | PT_Mono: pt_mono, 16 | }; 17 | 18 | export const chat_interface_info = 19 | "Use the Chat Interface to interact with your data. Your query will be used to retrieve relevant information and to construct a response. You can choose between different Large Language Models (LLM) to create a response."; 20 | export const chunk_interface_info = 21 | "Use the Chunk Interface to browse through relevant chunks of your data, based on your last query. You can choose between different embeddings and retrieval techniques."; 22 | export const document_interface_info = 23 | "Use the Document Viewer to inspect your data and extracts of context that were used to generate responses to your queries. You can switch between showing the whole document and only showing the specific extract."; 24 | 25 | export const getWebSocketApiHost = () => { 26 | if (process.env.NODE_ENV === "development") { 27 | return "ws://localhost:8000/ws/generate_stream"; 28 | } 29 | // If you're serving the app directly through FastAPI, generate the WebSocket URL based on the current location. 30 | const protocol = window.location.protocol === "https:" ? "wss:" : "ws:"; 31 | const host = window.location.host; 32 | return `${protocol}//${host}/ws/generate_stream`; 33 | }; 34 | 35 | export function deepCopyRAGConfig(config: RAGConfig): RAGConfig { 36 | return JSON.parse(JSON.stringify(config)); 37 | } 38 | 39 | export const closeOnClick = (element?: HTMLElement) => { 40 | const elem = element || document.activeElement; 41 | if (elem && elem instanceof HTMLElement) { 42 | elem.blur(); 43 | } 44 | }; 45 | 46 | export function arrayBufferToBase64(buffer: ArrayBuffer): string { 47 | let binary = ""; 48 | const bytes = new Uint8Array(buffer); 49 | const len = bytes.byteLength; 50 | for (let i = 0; i < len; i++) { 51 | binary += String.fromCharCode(bytes[i]); 52 | } 53 | return btoa(binary); // Encode the binary string to base64 54 | } 55 | 56 | export const getImportWebSocketApiHost = () => { 57 | if (process.env.NODE_ENV === "development") { 58 | return "ws://localhost:8000/ws/import_files"; 59 | } 60 | // If you're serving the app directly through FastAPI, generate the WebSocket URL based on the current location. 61 | const protocol = window.location.protocol === "https:" ? "wss:" : "ws:"; 62 | const host = window.location.host; 63 | return `${protocol}//${host}/ws/import_files`; 64 | }; 65 | -------------------------------------------------------------------------------- /frontend/glsl.d.ts: -------------------------------------------------------------------------------- 1 | declare module "*.glsl" { 2 | const value: string; 3 | export default value; 4 | } 5 | -------------------------------------------------------------------------------- /frontend/next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | output: 'export', 4 | webpack: (config) => { 5 | config.module.rules.push({ 6 | test: /\.glsl$/, 7 | use: ['raw-loader'], 8 | }); 9 | return config; 10 | }, 11 | async redirects() { 12 | return [ 13 | { 14 | source: '/v1', 15 | destination: '/', 16 | permanent: true, 17 | }, 18 | { 19 | source: '/v1/:path*', 20 | destination: '/:path*', 21 | permanent: true, 22 | }, 23 | ]; 24 | }, 25 | }; 26 | 27 | // Set assetPrefix only in production/export mode 28 | if (process.env.NODE_ENV === 'production') { 29 | nextConfig.assetPrefix = '/static'; 30 | } 31 | 32 | module.exports = nextConfig; -------------------------------------------------------------------------------- /frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "verba", 3 | "version": "2.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build && cp -r out/* ../goldenverba/server/frontend/out/ && rm -r out", 8 | "start": "next start -H 0.0.0.0 -p 8080", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "@mdx-js/mdx": "^2.3.0", 13 | "@mdx-js/react": "^2.3.0", 14 | "@next/third-parties": "^14.2.3", 15 | "@react-pdf/renderer": "^3.4.4", 16 | "@react-three/drei": "^9.108.4", 17 | "@react-three/fiber": "^8.16.8", 18 | "@types/node": "20.5.0", 19 | "@types/react": "18.2.20", 20 | "@types/react-dom": "18.2.7", 21 | "@types/three": "^0.166.0", 22 | "autoprefixer": "10.4.15", 23 | "date-fns": "^3.6.0", 24 | "eslint": "8.47.0", 25 | "eslint-config-next": "^14.2.6", 26 | "framer-motion": "^11.3.31", 27 | "lil-gui": "^0.19.2", 28 | "next": "^14.2.25", 29 | "postcss": "8.4.27", 30 | "react": "^18.3.1", 31 | "react-colorful": "^5.6.1", 32 | "react-countup": "^6.4.2", 33 | "react-dom": "^18.3.1", 34 | "react-icons": "^4.11.0", 35 | "react-markdown": "^8.0.7", 36 | "react-spinners": "^0.13.8", 37 | "react-syntax-highlighter": "^15.5.0", 38 | "react-virtuoso": "^4.6.2", 39 | "react-window": "^1.8.9", 40 | "tailwindcss": "3.3.3", 41 | "three": "^0.166.1", 42 | "three-custom-shader-material": "5.4", 43 | "typescript": "5.1.6", 44 | "typewriter-effect": "^2.20.1" 45 | }, 46 | "devDependencies": { 47 | "@tailwindcss/typography": "^0.5.12", 48 | "@types/react-syntax-highlighter": "^15.5.7", 49 | "@types/react-window": "^1.8.5", 50 | "daisyui": "^4.10.1", 51 | "prettier": "^3.2.5", 52 | "raw-loader": "^4.0.2" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /frontend/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /frontend/public/alps_field_1k.hdr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/frontend/public/alps_field_1k.hdr -------------------------------------------------------------------------------- /frontend/public/cloudy.hdr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/frontend/public/cloudy.hdr -------------------------------------------------------------------------------- /frontend/public/cool_cap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/frontend/public/cool_cap.png -------------------------------------------------------------------------------- /frontend/public/fire_cap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/frontend/public/fire_cap.png -------------------------------------------------------------------------------- /frontend/public/gold_matcap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/frontend/public/gold_matcap.png -------------------------------------------------------------------------------- /frontend/public/golden_cap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/frontend/public/golden_cap.png -------------------------------------------------------------------------------- /frontend/public/ice_cap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/frontend/public/ice_cap.png -------------------------------------------------------------------------------- /frontend/public/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/frontend/public/icon.ico -------------------------------------------------------------------------------- /frontend/public/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/public/shaders/includes/simplexNoise4d.glsl: -------------------------------------------------------------------------------- 1 | // Simplex 4D Noise 2 | // by Ian McEwan, Ashima Arts 3 | // 4 | vec4 permute(vec4 x){return mod(((x*34.0)+1.0)*x, 289.0);} 5 | float permute(float x){return floor(mod(((x*34.0)+1.0)*x, 289.0));} 6 | vec4 taylorInvSqrt(vec4 r){return 1.79284291400159 - 0.85373472095314 * r;} 7 | float taylorInvSqrt(float r){return 1.79284291400159 - 0.85373472095314 * r;} 8 | 9 | vec4 grad4(float j, vec4 ip) 10 | { 11 | const vec4 ones = vec4(1.0, 1.0, 1.0, -1.0); 12 | vec4 p,s; 13 | 14 | p.xyz = floor( fract (vec3(j) * ip.xyz) * 7.0) * ip.z - 1.0; 15 | p.w = 1.5 - dot(abs(p.xyz), ones.xyz); 16 | s = vec4(lessThan(p, vec4(0.0))); 17 | p.xyz = p.xyz + (s.xyz*2.0 - 1.0) * s.www; 18 | 19 | return p; 20 | 21 | 22 | float simplexNoise4d(vec4 v) 23 | { 24 | const vec2 C = vec2( 0.138196601125010504, // (5 - sqrt(5))/20 G4 25 | 0.309016994374947451); // (sqrt(5) - 1)/4 F4 26 | // First corner 27 | vec4 i = floor(v + dot(v, C.yyyy) ); 28 | vec4 x0 = v - i + dot(i, C.xxxx); 29 | 30 | // Other corners 31 | 32 | // Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI) 33 | vec4 i0; 34 | 35 | vec3 isX = step( x0.yzw, x0.xxx ); 36 | vec3 isYZ = step( x0.zww, x0.yyz ); 37 | // i0.x = dot( isX, vec3( 1.0 ) ); 38 | i0.x = isX.x + isX.y + isX.z; 39 | i0.yzw = 1.0 - isX; 40 | 41 | // i0.y += dot( isYZ.xy, vec2( 1.0 ) ); 42 | i0.y += isYZ.x + isYZ.y; 43 | i0.zw += 1.0 - isYZ.xy; 44 | 45 | i0.z += isYZ.z; 46 | i0.w += 1.0 - isYZ.z; 47 | 48 | // i0 now contains the unique values 0,1,2,3 in each channel 49 | vec4 i3 = clamp( i0, 0.0, 1.0 ); 50 | vec4 i2 = clamp( i0-1.0, 0.0, 1.0 ); 51 | vec4 i1 = clamp( i0-2.0, 0.0, 1.0 ); 52 | 53 | // x0 = x0 - 0.0 + 0.0 * C 54 | vec4 x1 = x0 - i1 + 1.0 * C.xxxx; 55 | vec4 x2 = x0 - i2 + 2.0 * C.xxxx; 56 | vec4 x3 = x0 - i3 + 3.0 * C.xxxx; 57 | vec4 x4 = x0 - 1.0 + 4.0 * C.xxxx; 58 | 59 | // Permutations 60 | i = mod(i, 289.0); 61 | float j0 = permute( permute( permute( permute(i.w) + i.z) + i.y) + i.x); 62 | vec4 j1 = permute( permute( permute( permute ( 63 | i.w + vec4(i1.w, i2.w, i3.w, 1.0 )) 64 | + i.z + vec4(i1.z, i2.z, i3.z, 1.0 )) 65 | + i.y + vec4(i1.y, i2.y, i3.y, 1.0 )) 66 | + i.x + vec4(i1.x, i2.x, i3.x, 1.0 )); 67 | // Gradients 68 | // ( 7*7*6 points uniformly over a cube, mapped onto a 4-octahedron.) 69 | // 7*7*6 = 294, which is close to the ring size 17*17 = 289. 70 | 71 | vec4 ip = vec4(1.0/294.0, 1.0/49.0, 1.0/7.0, 0.0) ; 72 | 73 | vec4 p0 = grad4(j0, ip); 74 | vec4 p1 = grad4(j1.x, ip); 75 | vec4 p2 = grad4(j1.y, ip); 76 | vec4 p3 = grad4(j1.z, ip); 77 | vec4 p4 = grad4(j1.w, ip); 78 | 79 | // Normalise gradients 80 | vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3))); 81 | p0 *= norm.x; 82 | p1 *= norm.y; 83 | p2 *= norm.z; 84 | p3 *= norm.w; 85 | p4 *= taylorInvSqrt(dot(p4,p4)); 86 | 87 | // Mix contributions from the five corners 88 | vec3 m0 = max(0.6 - vec3(dot(x0,x0), dot(x1,x1), dot(x2,x2)), 0.0); 89 | vec2 m1 = max(0.6 - vec2(dot(x3,x3), dot(x4,x4) ), 0.0); 90 | m0 = m0 * m0; 91 | m1 = m1 * m1; 92 | return 49.0 * ( dot(m0*m0, vec3( dot( p0, x0 ), dot( p1, x1 ), dot( p2, x2 ))) 93 | + dot(m1*m1, vec2( dot( p3, x3 ), dot( p4, x4 ) ) ) ) ; 94 | 95 | } -------------------------------------------------------------------------------- /frontend/public/shaders/wobble/fragment.glsl: -------------------------------------------------------------------------------- 1 | varying float vWobble; 2 | uniform vec3 uColorA; 3 | uniform vec3 uColorB; 4 | 5 | void main() 6 | { 7 | float colorMix = smoothstep(-1.0, 1.0, vWobble); 8 | csm_DiffuseColor.rgb = mix(uColorA, uColorB, colorMix); 9 | } -------------------------------------------------------------------------------- /frontend/public/shiny_cap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/frontend/public/shiny_cap.png -------------------------------------------------------------------------------- /frontend/public/silver_cap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/frontend/public/silver_cap.png -------------------------------------------------------------------------------- /frontend/public/verba.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/frontend/public/verba.glb -------------------------------------------------------------------------------- /frontend/public/verba.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/frontend/public/verba.png -------------------------------------------------------------------------------- /frontend/public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/public/weaviate.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/frontend/public/weaviate.glb -------------------------------------------------------------------------------- /frontend/public/weaviate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/frontend/public/weaviate.png -------------------------------------------------------------------------------- /frontend/tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss"; 2 | const colors = require("tailwindcss/colors"); 3 | 4 | const config: Config = { 5 | purge: { 6 | options: { 7 | safelist: [ 8 | "bg-yellow-300", 9 | "bg-gray-300", 10 | "bg-gray-400", 11 | "bg-zinc-300", 12 | "bg-zinc-400", 13 | "bg-red-300", 14 | "bg-green-300", 15 | "bg-cyan-300", 16 | "bg-fuchsia-300", 17 | "bg-yellow-400", 18 | "bg-green-400", 19 | "bg-cyan-400", 20 | "bg-fuchsia-400", 21 | "bg-red-400", 22 | "bg-indigo-400", 23 | // ... any other dynamically constructed classes 24 | ], 25 | }, 26 | }, 27 | content: [ 28 | "./pages/**/*.{js,ts,jsx,tsx,mdx}", 29 | "./components/**/*.{js,ts,jsx,tsx,mdx}", 30 | "./app/**/*.{js,ts,jsx,tsx,mdx}", 31 | ], 32 | theme: { 33 | screens: { 34 | sm: "100px", 35 | md: "930px", 36 | lg: "1280px", 37 | full: "1700px", 38 | }, 39 | colors: { 40 | transparent: "transparent", 41 | current: "currentColor", 42 | black: colors.black, 43 | white: colors.white, 44 | gray: colors.gray, 45 | emerald: colors.emerald, 46 | indigo: colors.indigo, 47 | green: colors.green, 48 | blue: colors.blue, 49 | yellow: colors.yellow, 50 | red: colors.red, 51 | }, 52 | fontSize: { 53 | xs: "0.75rem", 54 | sm: "0.8rem", 55 | base: "1rem", 56 | xl: "1.25rem", 57 | "2xl": "1.563rem", 58 | "3xl": "1.953rem", 59 | "4xl": "2.441rem", 60 | "5xl": "3.052rem", 61 | }, 62 | extend: { 63 | colors: { 64 | "bg-verba": "var(--bg-verba, #FEF7F7)", 65 | "bg-alt-verba": "var(--bg-alt-verba, #FFFFFF)", 66 | "button-verba": "var(--button-verba, #EFEFEF)", 67 | "button-hover-verba": "var(--button-hover-verba, #DCDCDC)", 68 | "primary-verba": "var(--primary-verba, #FDFF91)", 69 | "secondary-verba": "var(--secondary-verba, #90FFA8)", 70 | "warning-verba": "var(--warning-verba, #FF8399)", 71 | "text-verba": "var(--text-verba, #161616)", 72 | "text-alt-verba": "var(--text-alt-verba, #8E8E8E)", 73 | "text-verba-button": "var(--text-verba-button, #161616)", 74 | "text-alt-verba-button": "var(--text-alt-verba-button, #8E8E8E)", 75 | }, 76 | backgroundImage: { 77 | "gradient-radial": "radial-gradient(var(--tw-gradient-stops))", 78 | "gradient-conic": 79 | "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))", 80 | }, 81 | }, 82 | }, 83 | plugins: [require("daisyui"), require("@tailwindcss/typography")], 84 | 85 | daisyui: { 86 | themes: ["light", "dark"], 87 | }, 88 | }; 89 | export default config; 90 | -------------------------------------------------------------------------------- /frontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "downlevelIteration": true, 4 | "target": "es5", 5 | "lib": [ 6 | "dom", 7 | "dom.iterable", 8 | "esnext" 9 | ], 10 | "allowJs": true, 11 | "skipLibCheck": true, 12 | "strict": true, 13 | "forceConsistentCasingInFileNames": true, 14 | "noEmit": true, 15 | "esModuleInterop": true, 16 | "module": "esnext", 17 | "moduleResolution": "bundler", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "jsx": "preserve", 21 | "incremental": true, 22 | "plugins": [ 23 | { 24 | "name": "next" 25 | } 26 | ], 27 | "paths": { 28 | "@/*": [ 29 | "./*" 30 | ] 31 | } 32 | }, 33 | "include": [ 34 | "next-env.d.ts", 35 | "**/*.ts", 36 | "**/*.tsx", 37 | ".next/types/**/*.ts", 38 | "../verba-rag/server/frontend/types/**/*.ts" 39 | ], 40 | "exclude": [ 41 | "node_modules" 42 | ] 43 | } -------------------------------------------------------------------------------- /goldenverba/.env.example: -------------------------------------------------------------------------------- 1 | 2 | # WEAVIATE_URL_VERBA= 3 | # WEAVIATE_API_KEY_VERBA= 4 | 5 | # OPENAI_API_KEY= 6 | # OPENAI_BASE_URL=http://0.0.0.0:8000 7 | 8 | # COHERE_API_KEY= 9 | 10 | # VOYAGE_API_KEY= 11 | # ANTHROPIC_API_KEY= 12 | 13 | # EMBEDDING_SERVICE_URL= 14 | # EMBEDDING_SERVICE_KEY= 15 | 16 | # FIRECRAWL_API_KEY= 17 | 18 | # UNSTRUCTURED_API_KEY= 19 | # UNSTRUCTURED_API_URL=https://api.unstructuredapp.io/general/v0/general 20 | 21 | # GITHUB_TOKEN= 22 | # GITLAB_TOKEN= 23 | 24 | # OLLAMA_URL=http://localhost:11434 25 | 26 | # UPSTAGE_API_KEY= 27 | 28 | # NOVITA_API_KEY= 29 | -------------------------------------------------------------------------------- /goldenverba/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/goldenverba/__init__.py -------------------------------------------------------------------------------- /goldenverba/components/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/goldenverba/components/__init__.py -------------------------------------------------------------------------------- /goldenverba/components/chunk.py: -------------------------------------------------------------------------------- 1 | from spacy.tokens import Doc, Span 2 | 3 | 4 | class Chunk: 5 | def __init__( 6 | self, 7 | content: str = "", 8 | content_without_overlap: str = "", 9 | chunk_id: str = "", 10 | start_i: int = 0, 11 | end_i: int = 0, 12 | ): 13 | self.content = content 14 | self.title = "" 15 | self.chunk_id = chunk_id 16 | self.vector = None 17 | self.doc_uuid = None 18 | self.pca = [0, 0, 0] 19 | self.start_i = start_i 20 | self.end_i = end_i 21 | self.content_without_overlap = content_without_overlap 22 | self.labels = [] 23 | 24 | def to_json(self) -> dict: 25 | """Convert the Chunk object to a dictionary.""" 26 | return { 27 | "content": self.content, 28 | "chunk_id": self.chunk_id, 29 | "doc_uuid": self.doc_uuid, 30 | "title": self.title, 31 | "pca": self.pca, 32 | "start_i": self.start_i, 33 | "end_i": self.end_i, 34 | "content_without_overlap": self.content_without_overlap, 35 | "labels": self.labels, 36 | } 37 | 38 | @classmethod 39 | def from_json(cls, data: dict): 40 | """Construct a Chunk object from a dictionary.""" 41 | chunk = cls( 42 | content=data.get("content", ""), 43 | title=data.get("title", ""), 44 | chunk_id=data.get("chunk_id", 0), 45 | start_i=data.get("start_i", 0), 46 | end_i=data.get("end_i", 0), 47 | content_without_overlap=data.get("content_without_overlap", ""), 48 | labels=data.get("labels", []), 49 | ) 50 | chunk.doc_uuid = (data.get("doc_uuid", ""),) 51 | return chunk 52 | -------------------------------------------------------------------------------- /goldenverba/components/chunking/CodeChunker.py: -------------------------------------------------------------------------------- 1 | import contextlib 2 | 3 | with contextlib.suppress(Exception): 4 | from langchain_text_splitters import ( 5 | Language, 6 | RecursiveCharacterTextSplitter, 7 | ) 8 | 9 | from goldenverba.components.chunk import Chunk 10 | from goldenverba.components.interfaces import Chunker 11 | from goldenverba.components.document import Document 12 | from goldenverba.components.types import InputConfig 13 | from goldenverba.components.interfaces import Embedding 14 | 15 | 16 | class CodeChunker(Chunker): 17 | """ 18 | CodeChunker for Verba using LangChain. 19 | """ 20 | 21 | def __init__(self): 22 | super().__init__() 23 | self.name = "Code" 24 | self.requires_library = ["langchain_text_splitters"] 25 | self.description = "Split code based on programming language using LangChain" 26 | self.config = { 27 | "Language": InputConfig( 28 | type="dropdown", 29 | value="python", 30 | description="Select programming language", 31 | values=[e.value for e in Language], 32 | ), 33 | "Chunk Size": InputConfig( 34 | type="number", 35 | value=500, 36 | description="Choose how many characters per chunk", 37 | values=[], 38 | ), 39 | "Chunk Overlap": InputConfig( 40 | type="number", 41 | value=50, 42 | description="Choose how many characters overlap between chunks", 43 | values=[], 44 | ), 45 | } 46 | 47 | async def chunk( 48 | self, 49 | config: dict, 50 | documents: list[Document], 51 | embedder: Embedding | None = None, 52 | embedder_config: dict | None = None, 53 | ) -> list[Document]: 54 | 55 | language = config["Language"].value 56 | chunk_size = config["Chunk Size"].value 57 | chunk_overlap = config["Chunk Overlap"].value 58 | 59 | text_splitter = RecursiveCharacterTextSplitter.from_language( 60 | language=language, chunk_size=chunk_size, chunk_overlap=chunk_overlap 61 | ) 62 | 63 | for document in documents: 64 | 65 | # Skip if document already contains chunks 66 | if len(document.chunks) > 0: 67 | continue 68 | 69 | char_end_i = -1 70 | for i, chunk in enumerate(text_splitter.split_text(document.content)): 71 | 72 | if chunk_overlap == 0: 73 | char_start_i = char_end_i + 1 74 | char_end_i = char_start_i + len(chunk) 75 | else: 76 | # not implemented, requires complex calculations as to whether the overlap contained a 'good' chunk 77 | char_start_i = None 78 | char_end_i = None 79 | 80 | document.chunks.append( 81 | Chunk( 82 | content=chunk, 83 | chunk_id=i, 84 | start_i=char_start_i, 85 | end_i=char_end_i, 86 | content_without_overlap=chunk, 87 | ) 88 | ) 89 | 90 | return documents 91 | -------------------------------------------------------------------------------- /goldenverba/components/chunking/HTMLChunker.py: -------------------------------------------------------------------------------- 1 | import contextlib 2 | 3 | with contextlib.suppress(Exception): 4 | from langchain_text_splitters import HTMLHeaderTextSplitter 5 | 6 | from goldenverba.components.chunk import Chunk 7 | from goldenverba.components.interfaces import Chunker 8 | from goldenverba.components.document import Document 9 | from goldenverba.components.interfaces import Embedding 10 | 11 | 12 | class HTMLChunker(Chunker): 13 | """ 14 | HTMLChunker for Verba using LangChain. 15 | """ 16 | 17 | def __init__(self): 18 | super().__init__() 19 | self.name = "HTML" 20 | self.requires_library = ["langchain_text_splitters"] 21 | self.description = "Split documents based on HTML tags using LangChain" 22 | 23 | async def chunk( 24 | self, 25 | config: dict, 26 | documents: list[Document], 27 | embedder: Embedding | None = None, 28 | embedder_config: dict | None = None, 29 | ) -> list[Document]: 30 | 31 | text_splitter = HTMLHeaderTextSplitter( 32 | headers_to_split_on=[ 33 | ("h1", "Header 1"), 34 | ("h2", "Header 2"), 35 | ("h3", "Header 3"), 36 | ("h4", "Header 4"), 37 | ] 38 | ) 39 | 40 | for document in documents: 41 | 42 | # Skip if document already contains chunks 43 | if len(document.chunks) > 0: 44 | continue 45 | 46 | for i, chunk in enumerate(text_splitter.split_text(document.content)): 47 | 48 | chunk_text = "" 49 | 50 | # append title and page content (should only be one header as we are splitting at header so index at 0), if a header is found 51 | if len(chunk.metadata) > 0: 52 | chunk_text += list(chunk.metadata.values())[0] + "\n" 53 | 54 | # append page content (always there) 55 | chunk_text += chunk.page_content 56 | 57 | document.chunks.append( 58 | Chunk( 59 | content=chunk_text, 60 | chunk_id=i, 61 | start_i=None, # not implemented as HTML text splitter changes the actual document (removes tags) 62 | end_i=None, 63 | content_without_overlap=chunk_text, 64 | ) 65 | ) 66 | 67 | return documents 68 | -------------------------------------------------------------------------------- /goldenverba/components/chunking/JSONChunker.py: -------------------------------------------------------------------------------- 1 | import contextlib 2 | 3 | import json 4 | 5 | with contextlib.suppress(Exception): 6 | from langchain_text_splitters import ( 7 | RecursiveJsonSplitter, 8 | ) 9 | 10 | from goldenverba.components.chunk import Chunk 11 | from goldenverba.components.interfaces import Chunker 12 | from goldenverba.components.document import Document 13 | from goldenverba.components.types import InputConfig 14 | from goldenverba.components.interfaces import Embedding 15 | 16 | 17 | class JSONChunker(Chunker): 18 | """ 19 | JSONChunker for Verba using LangChain. 20 | """ 21 | 22 | def __init__(self): 23 | super().__init__() 24 | self.name = "JSON" 25 | self.requires_library = ["langchain_text_splitters"] 26 | self.description = "Split json files using LangChain" 27 | self.config = { 28 | "Chunk Size": InputConfig( 29 | type="number", 30 | value=500, 31 | description="Choose how many characters per chunks", 32 | values=[], 33 | ), 34 | } 35 | 36 | async def chunk( 37 | self, 38 | config: dict, 39 | documents: list[Document], 40 | embedder: Embedding | None = None, 41 | embedder_config: dict | None = None, 42 | ) -> list[Document]: 43 | 44 | units = int(config["Chunk Size"].value) 45 | 46 | text_splitter = RecursiveJsonSplitter(max_chunk_size=units) 47 | 48 | for document in documents: 49 | 50 | json_obj = json.loads(document.content) 51 | 52 | # Skip if document already contains chunks 53 | if len(document.chunks) > 0: 54 | continue 55 | 56 | char_end_i = -1 57 | for i, chunk in enumerate(text_splitter.split_text(json_obj)): 58 | 59 | char_start_i = char_end_i + 1 60 | char_end_i = char_start_i + len(chunk) 61 | 62 | document.chunks.append( 63 | Chunk( 64 | content=chunk, 65 | chunk_id=i, 66 | start_i=None, # not implemented as the splitter modifies the outputs 67 | end_i=None, 68 | content_without_overlap=chunk, 69 | ) 70 | ) 71 | 72 | return documents 73 | -------------------------------------------------------------------------------- /goldenverba/components/chunking/MarkdownChunker.py: -------------------------------------------------------------------------------- 1 | import contextlib 2 | 3 | with contextlib.suppress(Exception): 4 | from langchain_text_splitters import MarkdownHeaderTextSplitter 5 | from langchain_core.documents import Document as LangChainDocument 6 | 7 | from goldenverba.components.chunk import Chunk 8 | from goldenverba.components.interfaces import Chunker 9 | from goldenverba.components.document import Document 10 | from goldenverba.components.interfaces import Embedding 11 | 12 | 13 | HEADERS_TO_SPLIT_ON = [ 14 | ("#", "Header 1"), 15 | ("##", "Header 2"), 16 | ("###", "Header 3"), 17 | ] 18 | 19 | 20 | def get_header_values( 21 | split_doc: LangChainDocument, 22 | ) -> list[str]: 23 | """ 24 | Get the text values of the headers in the LangChain Document resulting from a split. 25 | """ 26 | # This function uses an explicit list of header keys because the LangChain Document 27 | # metadata is a dictionary with arbitrary entries, some of which may not be headers. 28 | header_keys = [header_key for _, header_key in HEADERS_TO_SPLIT_ON] 29 | 30 | return [ 31 | header_value 32 | for header_key in header_keys 33 | if (header_value := split_doc.metadata.get(header_key)) is not None 34 | ] 35 | 36 | 37 | class MarkdownChunker(Chunker): 38 | """ 39 | MarkdownChunker for Verba using LangChain. 40 | """ 41 | 42 | def __init__(self): 43 | super().__init__() 44 | self.name = "Markdown" 45 | self.requires_library = ["langchain_text_splitters"] 46 | self.description = ( 47 | "Split documents based on markdown formatting using LangChain" 48 | ) 49 | 50 | async def chunk( 51 | self, 52 | config: dict, 53 | documents: list[Document], 54 | embedder: Embedding | None = None, 55 | embedder_config: dict | None = None, 56 | ) -> list[Document]: 57 | 58 | text_splitter = MarkdownHeaderTextSplitter( 59 | headers_to_split_on=HEADERS_TO_SPLIT_ON 60 | ) 61 | 62 | char_end_i = -1 63 | for document in documents: 64 | 65 | # Skip if document already contains chunks 66 | if len(document.chunks) > 0: 67 | continue 68 | 69 | for i, split_doc in enumerate(text_splitter.split_text(document.content)): 70 | 71 | chunk_text = "" 72 | 73 | # Add header content to retain context and improve retrieval 74 | header_values = get_header_values(split_doc) 75 | for header_value in header_values: 76 | chunk_text += header_value + "\n" 77 | 78 | # append page content (always there) 79 | chunk_text += split_doc.page_content 80 | 81 | char_start_i = char_end_i + 1 82 | char_end_i = char_start_i + len(chunk_text) 83 | 84 | document.chunks.append( 85 | Chunk( 86 | content=chunk_text, 87 | chunk_id=i, 88 | start_i=None, # not implemented as text splitter augments the document 89 | end_i=None, 90 | content_without_overlap=chunk_text, 91 | ) 92 | ) 93 | 94 | return documents 95 | -------------------------------------------------------------------------------- /goldenverba/components/chunking/RecursiveChunker.py: -------------------------------------------------------------------------------- 1 | import contextlib 2 | 3 | with contextlib.suppress(Exception): 4 | from langchain_text_splitters import RecursiveCharacterTextSplitter 5 | 6 | from goldenverba.components.chunk import Chunk 7 | from goldenverba.components.interfaces import Chunker 8 | from goldenverba.components.document import Document 9 | from goldenverba.components.types import InputConfig 10 | from goldenverba.components.interfaces import Embedding 11 | 12 | 13 | class RecursiveChunker(Chunker): 14 | """ 15 | RecursiveChunker for Verba using LangChain. 16 | """ 17 | 18 | def __init__(self): 19 | super().__init__() 20 | self.name = "Recursive" 21 | self.requires_library = ["langchain_text_splitters"] 22 | self.description = ( 23 | "Recursively split documents based on predefined characters using LangChain" 24 | ) 25 | self.config = { 26 | "Chunk Size": InputConfig( 27 | type="number", 28 | value=500, 29 | description="Choose how many characters per chunks", 30 | values=[], 31 | ), 32 | "Overlap": InputConfig( 33 | type="number", 34 | value=100, 35 | description="Choose how many characters per chunks", 36 | values=[], 37 | ), 38 | "Seperators": InputConfig( 39 | type="multi", 40 | value="", 41 | description="Select separators to split the text", 42 | values=[ 43 | "\n\n", 44 | "\n", 45 | " ", 46 | ".", 47 | ",", 48 | "\u200b", 49 | "\uff0c", 50 | "\u3001", 51 | "\uff0e", 52 | "\u3002", 53 | "", 54 | ], 55 | ), 56 | } 57 | 58 | async def chunk( 59 | self, 60 | config: dict, 61 | documents: list[Document], 62 | embedder: Embedding | None = None, 63 | embedder_config: dict | None = None, 64 | ) -> list[Document]: 65 | 66 | units = int(config["Chunk Size"].value) 67 | overlap = int(config["Overlap"].value) 68 | seperators = config["Seperators"].values 69 | 70 | text_splitter = RecursiveCharacterTextSplitter( 71 | chunk_size=units, 72 | chunk_overlap=overlap, 73 | length_function=len, 74 | is_separator_regex=False, 75 | separators=seperators, 76 | ) 77 | 78 | for document in documents: 79 | 80 | # Skip if document already contains chunks 81 | if len(document.chunks) > 0: 82 | continue 83 | 84 | # char_end_i = -1 85 | for i, chunk in enumerate(text_splitter.split_text(document.content)): 86 | 87 | # leavingt this commented because this _does_ work but the text splitter strips whitespace and therefore modifies the original doc 88 | # if overlap == 0: 89 | # char_start_i = char_end_i + 1 90 | # char_end_i = char_start_i + len(chunk) 91 | # else: 92 | 93 | # not implemented because it uses intelligent chunking to find start of token 94 | char_start_i = None 95 | char_end_i = None 96 | 97 | document.chunks.append( 98 | Chunk( 99 | content=chunk, 100 | chunk_id=i, 101 | start_i=char_start_i, 102 | end_i=char_end_i, 103 | content_without_overlap=chunk, 104 | ) 105 | ) 106 | 107 | return documents 108 | -------------------------------------------------------------------------------- /goldenverba/components/chunking/SentenceChunker.py: -------------------------------------------------------------------------------- 1 | from wasabi import msg 2 | 3 | from goldenverba.components.chunk import Chunk 4 | from goldenverba.components.interfaces import Chunker 5 | from goldenverba.components.document import Document 6 | from goldenverba.components.types import InputConfig 7 | from goldenverba.components.interfaces import Embedding 8 | 9 | 10 | class SentenceChunker(Chunker): 11 | """ 12 | SentenceChunker for Verba built with spacy. 13 | """ 14 | 15 | def __init__(self): 16 | super().__init__() 17 | self.name = "Sentence" 18 | self.description = "Splits documents based on word tokens" 19 | self.config = { 20 | "Sentences": InputConfig( 21 | type="number", 22 | value=5, 23 | description="Choose how many Sentences per chunks", 24 | values=[], 25 | ), 26 | "Overlap": InputConfig( 27 | type="number", 28 | value=1, 29 | description="Choose how many Sentences should overlap between chunks", 30 | values=[], 31 | ), 32 | } 33 | 34 | async def chunk( 35 | self, 36 | config: dict, 37 | documents: list[Document], 38 | embedder: Embedding | None = None, 39 | embedder_config: dict | None = None, 40 | ) -> list[Document]: 41 | 42 | units = int(config["Sentences"].value) 43 | overlap = int(config["Overlap"].value) 44 | 45 | for document in documents: 46 | 47 | doc = document.spacy_doc 48 | 49 | # Skip if document already contains chunks 50 | if len(document.chunks) > 0: 51 | continue 52 | 53 | sentences = [sent.text for sent in doc.sents] 54 | 55 | # If Split Size is higher than actual Token Count or if Split Size is Zero 56 | if units > len(sentences) or units == 0: 57 | document.chunks.append( 58 | Chunk( 59 | content=document.content, 60 | chunk_id=0, 61 | start_i=0, 62 | end_i=len(document.content), 63 | content_without_overlap=document.content, 64 | ) 65 | ) 66 | continue 67 | 68 | if overlap >= units: 69 | msg.warn( 70 | f"Overlap value is greater than unit (Units {config['Sentences'].value}/ Overlap {config['Overlap'].value})" 71 | ) 72 | overlap = units - 1 73 | 74 | i = 0 75 | split_id_counter = 0 76 | char_end_i = -1 77 | while i < len(sentences): 78 | 79 | # index at the sentence level 80 | start_i = i 81 | end_i = min(i + units, len(sentences)) 82 | 83 | overlap_start = max(0, end_i - overlap) 84 | chunk_text = " ".join(sentences[start_i:end_i]) 85 | chunk_text_without_overlap = " ".join(sentences[start_i:overlap_start]) 86 | 87 | # need to convert to index at the character level 88 | char_start_i = char_end_i + 1 89 | if i > 0: 90 | char_start_i -= sum([len(s) for s in sentences[start_i:(start_i + overlap)]]) + 1 91 | char_end_i = char_start_i + len(chunk_text) 92 | 93 | 94 | doc_chunk = Chunk( 95 | content=chunk_text, 96 | chunk_id=split_id_counter, 97 | start_i=char_start_i, 98 | end_i=char_end_i, 99 | content_without_overlap=chunk_text_without_overlap, 100 | ) 101 | 102 | document.chunks.append(doc_chunk) 103 | split_id_counter += 1 104 | 105 | # Exit loop if this was the last possible chunk 106 | if end_i == len(sentences): 107 | break 108 | 109 | i += units - overlap # Step forward, considering overlap 110 | 111 | return documents 112 | -------------------------------------------------------------------------------- /goldenverba/components/chunking/TokenChunker.py: -------------------------------------------------------------------------------- 1 | from wasabi import msg 2 | 3 | from goldenverba.components.chunk import Chunk 4 | from goldenverba.components.interfaces import Chunker 5 | from goldenverba.components.document import Document 6 | from goldenverba.components.types import InputConfig 7 | from goldenverba.components.interfaces import Embedding 8 | 9 | 10 | class TokenChunker(Chunker): 11 | """ 12 | TokenChunker for Verba built with spacy. 13 | """ 14 | 15 | def __init__(self): 16 | super().__init__() 17 | self.name = "Token" 18 | self.description = "Splits documents based on word tokens" 19 | self.config = { 20 | "Tokens": InputConfig( 21 | type="number", 22 | value=250, 23 | description="Choose how many Token per chunks", 24 | values=[], 25 | ), 26 | "Overlap": InputConfig( 27 | type="number", 28 | value=50, 29 | description="Choose how many Tokens should overlap between chunks", 30 | values=[], 31 | ), 32 | } 33 | 34 | async def chunk( 35 | self, 36 | config: dict[str, InputConfig], 37 | documents: list[Document], 38 | embedder: Embedding | None = None, 39 | embedder_config: dict | None = None, 40 | ) -> list[Document]: 41 | 42 | units = int(config["Tokens"].value) 43 | overlap = int(config["Overlap"].value) 44 | 45 | for document in documents: 46 | 47 | doc = document.spacy_doc 48 | 49 | # Skip if document already contains chunks 50 | if len(document.chunks) > 0: 51 | continue 52 | 53 | # If Split Size is higher than actual Token Count or if Split Size is Zero 54 | if units > len(doc) or units == 0: 55 | document.chunks.append( 56 | Chunk( 57 | content=document.content, 58 | chunk_id=0, 59 | start_i=0, 60 | end_i=len(document.content), 61 | content_without_overlap=document.content, 62 | ) 63 | ) 64 | continue 65 | 66 | if overlap >= units: 67 | msg.warn( 68 | f"Overlap value is greater than unit (Units {config['Tokens'].value}/ Overlap {config['Overlap'].value})" 69 | ) 70 | overlap = units - 1 71 | 72 | i = 0 73 | split_id_counter = 0 74 | while i < len(doc): 75 | start_i = i 76 | end_i = min(i + units + overlap, len(doc)) 77 | if end_i == len(doc): 78 | overlap_start = end_i 79 | else: 80 | overlap_start = min(i + units, end_i) 81 | 82 | chunk_text = doc[start_i:end_i].text 83 | chunk_text_without_overlap = doc[start_i:overlap_start].text 84 | 85 | # char_start_i = doc[start_i].idx 86 | if end_i == len(doc): 87 | char_end_i = doc[-1].idx + 1 88 | else: 89 | char_end_i = doc[end_i].idx 90 | 91 | doc_chunk = Chunk( 92 | content=chunk_text, 93 | chunk_id=split_id_counter, 94 | start_i=doc[start_i].idx, 95 | end_i=char_end_i, 96 | content_without_overlap=chunk_text_without_overlap, 97 | ) 98 | 99 | document.chunks.append(doc_chunk) 100 | split_id_counter += 1 101 | 102 | # Exit loop if this was the last possible chunk 103 | if end_i == len(doc): 104 | break 105 | 106 | i += units # Step forward, considering overlap 107 | 108 | return documents 109 | -------------------------------------------------------------------------------- /goldenverba/components/chunking/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/goldenverba/components/chunking/__init__.py -------------------------------------------------------------------------------- /goldenverba/components/chunking/chunking_examples.py: -------------------------------------------------------------------------------- 1 | from goldenverba.components.chunking.TokenChunker import TokenChunker 2 | from goldenverba.components.document import Document 3 | import asyncio 4 | 5 | 6 | async def run_token_chunker(): 7 | chunker = TokenChunker() 8 | 9 | document = Document(content="This is a test document.") 10 | 11 | config = chunker.config 12 | config["Tokens"].value = 1 13 | config["Overlap"].value = 0 14 | chunked_documents = await chunker.chunk(config, [document]) 15 | 16 | for doc in chunked_documents: 17 | print(f"Document content: {doc.content}") 18 | print("Chunks:") 19 | for i, chunk in enumerate(doc.chunks, 1): 20 | print(f" Chunk {i}: {chunk.content}") 21 | print() # Add a blank line between documents¬ 22 | 23 | 24 | asyncio.run(run_token_chunker()) 25 | -------------------------------------------------------------------------------- /goldenverba/components/embedding/CohereEmbedder.py: -------------------------------------------------------------------------------- 1 | import os 2 | import requests 3 | import aiohttp 4 | import json 5 | 6 | from goldenverba.components.interfaces import Embedding 7 | from goldenverba.components.types import InputConfig 8 | from goldenverba.components.util import get_environment, get_token 9 | 10 | from wasabi import msg 11 | 12 | 13 | class CohereEmbedder(Embedding): 14 | """ 15 | CohereEmbedder for Verba. 16 | """ 17 | 18 | def __init__(self): 19 | super().__init__() 20 | self.name = "Cohere" 21 | self.description = "Vectorizes documents and queries using Cohere" 22 | self.url = os.getenv("COHERE_BASE_URL", "https://api.cohere.com/v1") 23 | models = get_models(self.url, get_token("COHERE_API_KEY", None), "embed") 24 | 25 | self.config["Model"] = InputConfig( 26 | type="dropdown", 27 | value=models[0] if models else "", 28 | description="Select a Cohere Embedding Model", 29 | values=models if models else [], 30 | ) 31 | 32 | if get_token("COHERE_API_KEY") is None: 33 | self.config["API Key"] = InputConfig( 34 | type="password", 35 | value="", 36 | description="You can set your Cohere API Key here or set it as environment variable `COHERE_API_KEY`", 37 | values=[], 38 | ) 39 | 40 | async def vectorize(self, config: dict, content: list[str]) -> list[float]: 41 | model = config.get("Model", "embed-english-v3.0").value 42 | api_key = get_environment( 43 | config, "API Key", "COHERE_API_KEY", "No Cohere API Key found" 44 | ) 45 | 46 | headers = { 47 | "Content-Type": "application/json", 48 | "Authorization": f"bearer {api_key}", 49 | } 50 | 51 | # Function to split the content into chunks of up to 96 texts 52 | def chunks(lst, n): 53 | for i in range(0, len(lst), n): 54 | yield lst[i : i + n] 55 | 56 | all_embeddings = [] 57 | 58 | async with aiohttp.ClientSession() as session: 59 | for chunk in chunks(content, 96): 60 | data = {"texts": chunk, "model": model, "input_type": "search_document"} 61 | async with session.post( 62 | self.url + "/embed", data=json.dumps(data), headers=headers 63 | ) as response: 64 | response.raise_for_status() 65 | response_data = await response.json() 66 | embeddings = response_data.get("embeddings", []) 67 | all_embeddings.extend(embeddings) 68 | 69 | return all_embeddings 70 | 71 | 72 | def get_models(url: str, token: str, model_type: str): 73 | try: 74 | if token is None or token == "": 75 | return [ 76 | "embed-english-v3.0", 77 | "embed-multilingual-v3.0", 78 | "embed-english-light-v3.0", 79 | "embed-multilingual-light-v3.0", 80 | ] 81 | headers = {"Authorization": f"bearer {token}"} 82 | response = requests.get(url + "/models", headers=headers) 83 | data = response.json() 84 | if "models" in data: 85 | return [ 86 | model["name"] 87 | for model in data["models"] 88 | if model_type in model["endpoints"] 89 | ] 90 | except Exception as e: 91 | msg.warn(f"Couldn't fetch models from Cohere endpoint: {e}") 92 | return [ 93 | "embed-english-v3.0", 94 | "embed-multilingual-v3.0", 95 | "embed-english-light-v3.0", 96 | "embed-multilingual-light-v3.0", 97 | ] 98 | -------------------------------------------------------------------------------- /goldenverba/components/embedding/GoogleEmbedder.py: -------------------------------------------------------------------------------- 1 | from weaviate import Client 2 | from goldenverba.components.interfaces import Embedder 3 | from goldenverba.components.document import Document 4 | 5 | 6 | class GoogleEmbedder(Embedder): 7 | """ 8 | GoogleEmbedder for Verba. 9 | """ 10 | 11 | def __init__(self): 12 | super().__init__() 13 | self.name = "GoogleEmbedder" 14 | self.requires_env = ["GOOGLE_API_KEY"] 15 | self.description = "Embeds and retrieves objects using Google's text-embedding-preview-0409 model" 16 | self.vectorizer = "text2vec-palm" 17 | 18 | def embed( 19 | self, 20 | documents: list[Document], 21 | client: Client, 22 | logging: list[dict], 23 | ) -> bool: 24 | """Embed verba documents and its chunks to Weaviate 25 | @parameter: documents : list[Document] - List of Verba documents 26 | @parameter: client : Client - Weaviate Client 27 | @parameter: batch_size : int - Batch Size of Input 28 | @returns bool - Bool whether the embedding what successful. 29 | """ 30 | return self.import_data(documents, client, logging) 31 | -------------------------------------------------------------------------------- /goldenverba/components/embedding/OllamaEmbedder.py: -------------------------------------------------------------------------------- 1 | import os 2 | import requests 3 | from wasabi import msg 4 | import aiohttp 5 | from urllib.parse import urljoin 6 | 7 | from goldenverba.components.interfaces import Embedding 8 | from goldenverba.components.types import InputConfig 9 | from goldenverba.components.util import get_environment 10 | 11 | 12 | class OllamaEmbedder(Embedding): 13 | 14 | def __init__(self): 15 | super().__init__() 16 | self.name = "Ollama" 17 | self.url = os.getenv("OLLAMA_URL", "http://localhost:11434") 18 | self.description = f"Vectorizes documents and queries using Ollama. If your Ollama instance is not running on {self.url}, you can change the URL by setting the OLLAMA_URL environment variable." 19 | models = get_models(self.url) 20 | 21 | self.config = { 22 | "Model": InputConfig( 23 | type="dropdown", 24 | value=os.getenv("OLLAMA_EMBED_MODEL") or models[0], 25 | description=f"Select a installed Ollama model from {self.url}. You can change the URL by setting the OLLAMA_URL environment variable. ", 26 | values=models, 27 | ), 28 | } 29 | 30 | async def vectorize(self, config: dict, content: list[str]) -> list[float]: 31 | 32 | model = config.get("Model").value 33 | 34 | data = {"model": model, "input": content} 35 | 36 | async with aiohttp.ClientSession() as session: 37 | async with session.post(urljoin(self.url, "/api/embed"), json=data) as response: 38 | response.raise_for_status() 39 | data = await response.json() 40 | embeddings = data.get("embeddings", []) 41 | return embeddings 42 | 43 | 44 | def get_models(url: str): 45 | try: 46 | response = requests.get(urljoin(url, "/api/tags")) 47 | models = [model.get("name") for model in response.json().get("models")] 48 | if len(models) > 0: 49 | return models 50 | else: 51 | msg.info("No Ollama Model detected") 52 | return ["No Ollama Model detected"] 53 | except Exception as e: 54 | msg.info(f"Couldn't connect to Ollama {url}") 55 | return [f"Couldn't connect to Ollama {url}"] 56 | -------------------------------------------------------------------------------- /goldenverba/components/embedding/SentenceTransformersEmbedder.py: -------------------------------------------------------------------------------- 1 | from goldenverba.components.interfaces import Embedding 2 | from goldenverba.components.types import InputConfig 3 | 4 | try: 5 | from sentence_transformers import SentenceTransformer 6 | except Exception as e: 7 | pass 8 | 9 | 10 | class SentenceTransformersEmbedder(Embedding): 11 | """ 12 | SentenceTransformersEmbedder base class for Verba. 13 | """ 14 | 15 | def __init__(self): 16 | super().__init__() 17 | self.name = "SentenceTransformers" 18 | self.requires_library = ["sentence_transformers"] 19 | self.description = "Embeds and retrieves objects using SentenceTransformer" 20 | self.config = { 21 | "Model": InputConfig( 22 | type="dropdown", 23 | value="all-MiniLM-L6-v2", 24 | description="Select an HuggingFace Embedding Model", 25 | values=[ 26 | "all-MiniLM-L6-v2", 27 | "mixedbread-ai/mxbai-embed-large-v1", 28 | "all-mpnet-base-v2", 29 | "BAAI/bge-m3", 30 | "all-MiniLM-L12-v2", 31 | "paraphrase-MiniLM-L6-v2", 32 | ], 33 | ), 34 | } 35 | 36 | async def vectorize(self, config: dict, content: list[str]) -> list[float]: 37 | try: 38 | model_name = config.get("Model").value 39 | model = SentenceTransformer(model_name) 40 | embeddings = model.encode(content).tolist() 41 | return embeddings 42 | except Exception as e: 43 | raise Exception(f"Failed to vectorize chunks: {str(e)}") 44 | -------------------------------------------------------------------------------- /goldenverba/components/embedding/UpstageEmbedder.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | from typing import List 4 | import io 5 | 6 | import aiohttp 7 | from wasabi import msg 8 | 9 | from goldenverba.components.interfaces import Embedding 10 | from goldenverba.components.types import InputConfig 11 | from goldenverba.components.util import get_environment, get_token 12 | 13 | 14 | class UpstageEmbedder(Embedding): 15 | """UpstageEmbedder for Verba.""" 16 | 17 | def __init__(self): 18 | super().__init__() 19 | self.name = "Upstage" 20 | self.description = ( 21 | "Vectorizes documents and queries using Upstage Solar Embeddings" 22 | ) 23 | self.max_batch_size = 100 24 | 25 | # Fetch available models 26 | api_key = get_token("UPSTAGE_API_KEY") 27 | base_url = os.getenv("UPSTAGE_BASE_URL", "https://api.upstage.ai/v1/solar") 28 | 29 | # Set up configuration 30 | self.config = { 31 | "Model": InputConfig( 32 | type="dropdown", 33 | value="embedding-query", 34 | description="Select an Upstage Embedding Model", 35 | values=["embedding-query", "embedding-passage"], 36 | ) 37 | } 38 | 39 | # Add API Key and URL configs if not set in environment 40 | if api_key is None: 41 | self.config["API Key"] = InputConfig( 42 | type="password", 43 | value="", 44 | description="Upstage API Key (or set UPSTAGE_API_KEY env var)", 45 | values=[], 46 | ) 47 | if os.getenv("UPSTAGE_BASE_URL") is None: 48 | self.config["URL"] = InputConfig( 49 | type="text", 50 | value=base_url, 51 | description="Upstage API Base URL (if different from default)", 52 | values=[], 53 | ) 54 | 55 | async def vectorize(self, config: dict, content: List[str]) -> List[List[float]]: 56 | """Vectorize the input content using Upstage's API.""" 57 | model = config.get("Model", {"value": "embedding-query"}).value 58 | api_key = get_environment( 59 | config, "API Key", "UPSTAGE_API_KEY", "No Upstage API Key found" 60 | ) 61 | base_url = get_environment( 62 | config, "URL", "UPSTAGE_BASE_URL", "No Upstage URL found" 63 | ) 64 | 65 | headers = { 66 | "Content-Type": "application/json", 67 | "Authorization": f"Bearer {api_key}", 68 | } 69 | payload = {"input": content, "model": model} 70 | 71 | # Convert payload to BytesIO object 72 | payload_bytes = json.dumps(payload).encode("utf-8") 73 | payload_io = io.BytesIO(payload_bytes) 74 | 75 | async with aiohttp.ClientSession() as session: 76 | try: 77 | async with session.post( 78 | f"{base_url}/embeddings", 79 | headers=headers, 80 | data=payload_io, 81 | timeout=30, 82 | ) as response: 83 | response.raise_for_status() 84 | data = await response.json() 85 | 86 | if "data" not in data: 87 | raise ValueError(f"Unexpected API response: {data}") 88 | 89 | embeddings = [item["embedding"] for item in data["data"]] 90 | if len(embeddings) != len(content): 91 | raise ValueError( 92 | f"Mismatch in embedding count: got {len(embeddings)}, expected {len(content)}" 93 | ) 94 | 95 | return embeddings 96 | 97 | except aiohttp.ClientError as e: 98 | if isinstance(e, aiohttp.ClientResponseError) and e.status == 429: 99 | raise Exception("Rate limit exceeded. Waiting before retrying...") 100 | raise Exception(f"API request failed: {str(e)}") 101 | 102 | except Exception as e: 103 | msg.fail(f"Unexpected error: {type(e).__name__} - {str(e)}") 104 | raise 105 | 106 | @staticmethod 107 | def get_models(token: str, url: str) -> List[str]: 108 | """Return available embedding models for Upstage.""" 109 | # Upstage currently has two fixed models 110 | return ["embedding-query", "embedding-passage"] 111 | -------------------------------------------------------------------------------- /goldenverba/components/embedding/VoyageAIEmbedder.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | from typing import List 4 | import io 5 | 6 | import aiohttp 7 | from wasabi import msg 8 | 9 | from goldenverba.components.interfaces import Embedding 10 | from goldenverba.components.types import InputConfig 11 | from goldenverba.components.util import get_environment 12 | 13 | 14 | class VoyageAIEmbedder(Embedding): 15 | """VoyageAIEmbedder for Verba.""" 16 | 17 | def __init__(self): 18 | super().__init__() 19 | self.name = "VoyageAI" 20 | self.description = "Vectorizes documents and queries using VoyageAI" 21 | 22 | # Fetch available models 23 | api_key = os.getenv("VOYAGE_API_KEY") 24 | base_url = os.getenv("VOYAGE_BASE_URL", "https://api.voyageai.com/v1") 25 | models = self.get_models(api_key, base_url) 26 | 27 | # Set up configuration 28 | self.config = { 29 | "Model": InputConfig( 30 | type="dropdown", 31 | value=models[0], 32 | description="Select a VoyageAI Embedding Model", 33 | values=models, 34 | ) 35 | } 36 | 37 | # Add API Key and URL configs if not set in environment 38 | if api_key is None: 39 | self.config["API Key"] = InputConfig( 40 | type="password", 41 | value="", 42 | description="OpenAI API Key (or set OPENAI_API_KEY env var)", 43 | values=[], 44 | ) 45 | if os.getenv("VOYAGE_BASE_URL") is None: 46 | self.config["URL"] = InputConfig( 47 | type="text", 48 | value=base_url, 49 | description="OpenAI API Base URL (if different from default)", 50 | values=[], 51 | ) 52 | 53 | async def vectorize(self, config: dict, content: List[str]) -> List[List[float]]: 54 | """Vectorize the input content using VoyageAI's API.""" 55 | model = config.get("Model").value 56 | api_key = get_environment( 57 | config, "API Key", "VOYAGE_API_KEY", "No VoyageAI API Key found" 58 | ) 59 | base_url = get_environment( 60 | config, "URL", "VOYAGE_BASE_URL", "No VoyageAI URL found" 61 | ) 62 | 63 | headers = { 64 | "Content-Type": "application/json", 65 | "Authorization": f"Bearer {api_key}", 66 | } 67 | payload = {"input": content, "model": model} 68 | 69 | async with aiohttp.ClientSession() as session: 70 | try: 71 | async with session.post( 72 | f"{base_url}/embeddings", 73 | headers=headers, 74 | json=payload, # Use json parameter instead of data 75 | timeout=30, 76 | ) as response: 77 | if response.status == 400: 78 | error_body = await response.text() 79 | raise ValueError(f"Bad Request: {error_body}") 80 | response.raise_for_status() 81 | data = await response.json() 82 | 83 | if "data" not in data: 84 | raise ValueError(f"Unexpected API response: {data}") 85 | 86 | embeddings = [item["embedding"] for item in data["data"]] 87 | if len(embeddings) != len(content): 88 | raise ValueError( 89 | f"Mismatch in embedding count: got {len(embeddings)}, expected {len(content)}" 90 | ) 91 | 92 | return embeddings 93 | 94 | except aiohttp.ClientError as e: 95 | if isinstance(e, aiohttp.ClientResponseError) and e.status == 429: 96 | raise Exception("Rate limit exceeded. Waiting before retrying...") 97 | raise Exception(f"API request failed: {str(e)}") 98 | 99 | except Exception as e: 100 | msg.fail(f"Unexpected error: {type(e).__name__} - {str(e)}") 101 | raise 102 | 103 | @staticmethod 104 | def get_models(token: str, url: str) -> List[str]: 105 | """Fetch available embedding models from VoyageAI API.""" 106 | return [ 107 | "voyage-2", 108 | "voyage-large-2", 109 | "voyage-finance-2", 110 | "voyage-multilingual-2", 111 | "voyage-law-2", 112 | "voyage-code-2", 113 | ] 114 | -------------------------------------------------------------------------------- /goldenverba/components/embedding/WeaviateEmbedder.py: -------------------------------------------------------------------------------- 1 | import os 2 | import requests 3 | from wasabi import msg 4 | import aiohttp 5 | 6 | from goldenverba.components.interfaces import Embedding 7 | from goldenverba.components.types import InputConfig 8 | from goldenverba.components.util import get_environment 9 | 10 | 11 | class WeaviateEmbedder(Embedding): 12 | 13 | def __init__(self): 14 | super().__init__() 15 | self.name = "Weaviate" 16 | self.description = f"Vectorizes documents and queries using Weaviate's In-House Embedding Service." 17 | models = ["Embedding Service"] 18 | 19 | api_key = os.getenv("EMBEDDING_SERVICE_KEY") 20 | base_url = os.getenv( 21 | "EMBEDDING_SERVICE_URL", "" 22 | ) # Provide empty string as default 23 | 24 | self.config = { 25 | "Model": InputConfig( 26 | type="dropdown", 27 | value=models[0], 28 | description=f"Select a Weaviate Embedding Service Model", 29 | values=models, 30 | ), 31 | } 32 | 33 | if api_key == None: 34 | self.config["API Key"] = InputConfig( 35 | type="password", 36 | value="", 37 | description="Weaviate Embedding Service Key (or set EMBEDDING_SERVICE_KEY env var)", 38 | values=[], 39 | ) 40 | if base_url == "": 41 | self.config["URL"] = InputConfig( 42 | type="text", 43 | value="", # Use empty string as default value 44 | description="Weaviate Embedding Service URL (if different from default)", 45 | values=[], 46 | ) 47 | 48 | async def vectorize(self, config: dict, content: list[str]) -> list[float]: 49 | 50 | api_key = get_environment( 51 | config, 52 | "API Key", 53 | "EMBEDDING_SERVICE_KEY", 54 | "No Weaviate Embedding Service Key found", 55 | ) 56 | base_url = get_environment( 57 | config, 58 | "URL", 59 | "EMBEDDING_SERVICE_URL", 60 | "No Weaviate Embedding Service URL found", 61 | ) 62 | 63 | path = "/v1/embeddings/embed" 64 | 65 | data = {"is_search_query": False, "texts": content} 66 | 67 | async with aiohttp.ClientSession() as session: 68 | async with session.post( 69 | base_url + path, json=data, headers={"Authorization": f"{api_key}"} 70 | ) as response: 71 | response.raise_for_status() 72 | data = await response.json() 73 | embeddings = data.get("embeddings", []) 74 | return embeddings 75 | -------------------------------------------------------------------------------- /goldenverba/components/embedding/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/goldenverba/components/embedding/__init__.py -------------------------------------------------------------------------------- /goldenverba/components/generation/OllamaGenerator.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | import aiohttp 4 | from urllib.parse import urljoin 5 | from typing import List, Dict, AsyncGenerator 6 | 7 | from goldenverba.components.interfaces import Generator 8 | from goldenverba.components.embedding.OllamaEmbedder import get_models 9 | from goldenverba.components.types import InputConfig 10 | 11 | 12 | class OllamaGenerator(Generator): 13 | def __init__(self): 14 | super().__init__() 15 | self.name = "Ollama" 16 | self.url = os.getenv("OLLAMA_URL", "http://localhost:11434") 17 | self.description = f"Generate answers using Ollama. If your Ollama instance is not running on {self.url}, you can change the URL by setting the OLLAMA_URL environment variable." 18 | self.context_window = 10000 19 | 20 | # Fetch available models 21 | models = get_models(self.url) 22 | 23 | # Configure the model selection dropdown 24 | self.config["Model"] = InputConfig( 25 | type="dropdown", 26 | value=os.getenv("OLLAMA_MODEL") or models[0] if models else "", 27 | description=f"Select an installed Ollama model from {self.url}.", 28 | values=models, 29 | ) 30 | 31 | async def generate_stream( 32 | self, 33 | config: Dict, 34 | query: str, 35 | context: str, 36 | conversation: List[Dict] = [], 37 | ) -> AsyncGenerator[Dict, None]: 38 | model = config.get("Model").value 39 | system_message = config.get("System Message").value 40 | 41 | if not self.url: 42 | yield self._error_response("Missing Ollama URL") 43 | return 44 | 45 | messages = self._prepare_messages(query, context, conversation, system_message) 46 | data = {"model": model, "messages": messages} 47 | 48 | try: 49 | async with aiohttp.ClientSession() as session: 50 | async with session.post(urljoin(self.url, "/api/chat"), json=data) as response: 51 | async for line in response.content: 52 | if line.strip(): 53 | yield self._process_response(line) 54 | else: 55 | yield self._empty_response() 56 | 57 | except Exception as e: 58 | yield self._error_response( 59 | f"Unexpected error, make sure to have {model} installed: {str(e)}" 60 | ) 61 | 62 | def _prepare_messages( 63 | self, 64 | query: str, 65 | context: str, 66 | conversation: List[Dict], 67 | system_message: str, 68 | ) -> List[Dict]: 69 | """Prepare the message list for the Ollama API request.""" 70 | messages = [ 71 | {"role": "system", "content": system_message}, 72 | *[ 73 | {"role": message.type, "content": message.content} 74 | for message in conversation 75 | ], 76 | { 77 | "role": "user", 78 | "content": f"With this provided context: {context} Please answer this query: {query}", 79 | }, 80 | ] 81 | return messages 82 | 83 | @staticmethod 84 | def _process_response(line: bytes) -> Dict: 85 | """Process a single line of response from the Ollama API.""" 86 | json_data = json.loads(line.decode("utf-8")) 87 | 88 | if "error" in json_data: 89 | return { 90 | "message": json_data.get("error", "Unexpected Error"), 91 | "finish_reason": "stop", 92 | } 93 | 94 | return { 95 | "message": json_data.get("message", {}).get("content", ""), 96 | "finish_reason": "stop" if json_data.get("done", False) else "", 97 | } 98 | 99 | @staticmethod 100 | def _empty_response() -> Dict: 101 | """Return an empty response.""" 102 | return {"message": "", "finish_reason": "stop"} 103 | 104 | @staticmethod 105 | def _error_response(message: str) -> Dict: 106 | """Return an error response.""" 107 | return {"message": message, "finish_reason": "stop"} 108 | -------------------------------------------------------------------------------- /goldenverba/components/generation/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/goldenverba/components/generation/__init__.py -------------------------------------------------------------------------------- /goldenverba/components/reader/UnstructuredAPI.py: -------------------------------------------------------------------------------- 1 | import base64 2 | import io 3 | import os 4 | 5 | import requests 6 | from wasabi import msg 7 | import aiohttp 8 | 9 | from goldenverba.components.document import Document, create_document 10 | from goldenverba.components.interfaces import Reader 11 | from goldenverba.server.types import FileConfig 12 | from goldenverba.components.util import get_environment 13 | from goldenverba.components.types import InputConfig 14 | 15 | 16 | class UnstructuredReader(Reader): 17 | """ 18 | Unstructured API Reader for importing multiple file types using the Unstructured.io API. 19 | """ 20 | 21 | def __init__(self): 22 | super().__init__() 23 | self.requires_env = ["UNSTRUCTURED_API_KEY"] 24 | self.name = "Unstructured IO" 25 | self.description = "Uses the Unstructured API to import multiple file types such as plain text and documents" 26 | 27 | # Define configuration options 28 | self.config = { 29 | "Strategy": InputConfig( 30 | type="dropdown", 31 | value="auto", 32 | description="Set the extraction strategy", 33 | values=["auto", "hi_res", "ocr_only", "fast"], 34 | ) 35 | } 36 | 37 | if os.getenv("UNSTRUCTURED_API_KEY") is None: 38 | self.config["API Key"] = InputConfig( 39 | type="password", 40 | value="", 41 | description="Set your Unstructured API Key here or set it as an environment variable `UNSTRUCTURED_API_KEY`", 42 | values=[], 43 | ) 44 | 45 | if os.getenv("UNSTRUCTURED_API_URL") is None: 46 | self.config["API URL"] = InputConfig( 47 | type="text", 48 | value="https://api.unstructured.io/general/v0/general", 49 | description="Set the base URL to the Unstructured API or set it as an environment variable `UNSTRUCTURED_API_URL`", 50 | values=[], 51 | ) 52 | 53 | async def load( 54 | self, config: dict[str, InputConfig], fileConfig: FileConfig 55 | ) -> list[Document]: 56 | """ 57 | Load and process a file using the Unstructured API. 58 | """ 59 | # Validate and get API credentials 60 | token = get_environment( 61 | config, 62 | "API Key", 63 | "UNSTRUCTURED_API_KEY", 64 | "No Unstructured API Key detected", 65 | ) 66 | api_url = get_environment( 67 | config, "API URL", "UNSTRUCTURED_API_URL", "No Unstructured URL detected" 68 | ) 69 | 70 | # Validate strategy 71 | strategy = config["Strategy"].value 72 | if strategy not in ["auto", "hi_res", "ocr_only", "fast"]: 73 | raise ValueError(f"Invalid strategy: {strategy}") 74 | 75 | headers = { 76 | "accept": "application/json", 77 | "unstructured-api-key": token, 78 | } 79 | 80 | msg.info(f"Loading {fileConfig.filename}") 81 | 82 | file_data = aiohttp.FormData() 83 | file_data.add_field("strategy", strategy) 84 | file_bytes = io.BytesIO(base64.b64decode(fileConfig.content)) 85 | file_data.add_field( 86 | "files", 87 | file_bytes, 88 | filename=f"{fileConfig.filename}.{fileConfig.extension}", 89 | ) 90 | 91 | try: 92 | async with aiohttp.ClientSession() as session: 93 | async with session.post( 94 | api_url, headers=headers, data=file_data 95 | ) as response: 96 | response.raise_for_status() # Raise an exception for bad status codes 97 | json_response = await response.json() 98 | 99 | if "detail" in json_response: 100 | raise ValueError(f"API error: {json_response['detail']}") 101 | 102 | file_content = "".join( 103 | chunk.get("text", "") for chunk in json_response 104 | ) 105 | 106 | return [create_document(file_content, fileConfig)] 107 | 108 | except requests.RequestException as e: 109 | raise Exception( 110 | f"Unstructured API request failed for {fileConfig.filename}: {str(e)}" 111 | ) 112 | except Exception as e: 113 | raise Exception(f"Failed to process {fileConfig.filename}: {str(e)}") 114 | -------------------------------------------------------------------------------- /goldenverba/components/reader/UpstageDocumentParse.py: -------------------------------------------------------------------------------- 1 | import base64 2 | import io 3 | import os 4 | 5 | import requests 6 | from wasabi import msg 7 | import aiohttp 8 | 9 | from goldenverba.components.document import Document, create_document 10 | from goldenverba.components.interfaces import Reader 11 | from goldenverba.server.types import FileConfig 12 | from goldenverba.components.util import get_environment 13 | from goldenverba.components.types import InputConfig 14 | 15 | 16 | class UpstageDocumentParseReader(Reader): 17 | """ 18 | Upstage Document Parse API Reader for converting documents to structured HTML format. 19 | """ 20 | 21 | def __init__(self): 22 | super().__init__() 23 | self.requires_env = ["UPSTAGE_API_KEY"] 24 | self.name = "Upstage Parser" 25 | self.description = "Uses the Upstage Document Parse API to convert documents into structured HTML format" 26 | 27 | if os.getenv("UPSTAGE_API_KEY") is None: 28 | self.config["API Key"] = InputConfig( 29 | type="password", 30 | value="", 31 | description="Set your Upstage API Key here or set it as an environment variable `UPSTAGE_API_KEY`", 32 | values=[], 33 | ) 34 | 35 | if os.getenv("UPSTAGE_API_URL") is None: 36 | self.config["API URL"] = InputConfig( 37 | type="text", 38 | value="https://api.upstage.ai/v1/document-ai/document-parse", 39 | description="Set the base URL to the Upstage API", 40 | values=[], 41 | ) 42 | 43 | async def load( 44 | self, config: dict[str, InputConfig], fileConfig: FileConfig 45 | ) -> list[Document]: 46 | """ 47 | Load and process a file using the Upstage Document Parse API. 48 | """ 49 | # Get API credentials 50 | token = get_environment( 51 | config, 52 | "API Key", 53 | "UPSTAGE_API_KEY", 54 | "No Upstage API Key detected", 55 | ) 56 | api_url = get_environment( 57 | config, "API URL", "UPSTAGE_API_URL", "No Upstage API URL detected" 58 | ) 59 | 60 | headers = { 61 | "Authorization": f"Bearer {token}", 62 | } 63 | 64 | msg.info(f"Loading {fileConfig.filename}") 65 | 66 | file_data = aiohttp.FormData() 67 | file_bytes = io.BytesIO(base64.b64decode(fileConfig.content)) 68 | file_data.add_field( 69 | "document", 70 | file_bytes, 71 | filename=f"{fileConfig.filename}.{fileConfig.extension}", 72 | ) 73 | 74 | try: 75 | async with aiohttp.ClientSession() as session: 76 | async with session.post( 77 | api_url, headers=headers, data=file_data 78 | ) as response: 79 | response.raise_for_status() 80 | json_response = await response.json() 81 | 82 | if "content" not in json_response: 83 | raise ValueError(f"API error: Invalid response format") 84 | 85 | # Extract text content from HTML 86 | html_content = json_response["content"]["html"] 87 | # You might want to add HTML to text conversion here 88 | # For now, we'll use the HTML content directly 89 | return [create_document(html_content, fileConfig)] 90 | 91 | except aiohttp.ClientError as e: 92 | raise Exception( 93 | f"Upstage API request failed for {fileConfig.filename}: {str(e)}" 94 | ) 95 | except Exception as e: 96 | raise Exception(f"Failed to process {fileConfig.filename}: {str(e)}") 97 | -------------------------------------------------------------------------------- /goldenverba/components/reader/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/goldenverba/components/reader/__init__.py -------------------------------------------------------------------------------- /goldenverba/components/retriever/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/goldenverba/components/retriever/__init__.py -------------------------------------------------------------------------------- /goldenverba/components/types.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from typing import Literal, Union 3 | 4 | 5 | class InputConfig(BaseModel): 6 | type: Literal["number", "text", "dropdown", "password", "bool", "multi", "textarea"] 7 | value: Union[int, str, bool] 8 | description: str 9 | values: list[str] 10 | -------------------------------------------------------------------------------- /goldenverba/components/util.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import os 3 | 4 | # Step 1: Standardize the data 5 | def standardize_data(X): 6 | mean = np.mean(X, axis=0) 7 | std_dev = np.std(X, axis=0) 8 | return (X - mean) / std_dev 9 | 10 | # Step 2: Compute the covariance matrix 11 | def compute_covariance_matrix(X): 12 | return np.cov(X, rowvar=False) 13 | 14 | # Step 3: Perform eigenvalue decomposition of the covariance matrix 15 | def eigen_decomposition(C): 16 | eigenvalues, eigenvectors = np.linalg.eig(C) 17 | return eigenvalues, eigenvectors 18 | 19 | # Step 4: Sort the eigenvalues and their corresponding eigenvectors 20 | def sort_eigenvalues_eigenvectors(eigenvalues, eigenvectors): 21 | idx = eigenvalues.argsort()[::-1] 22 | sorted_eigenvalues = eigenvalues[idx] 23 | sorted_eigenvectors = eigenvectors[:, idx] 24 | return sorted_eigenvalues, sorted_eigenvectors 25 | 26 | # Step 5: Select the top k eigenvectors (principal components) 27 | def select_top_k_components(eigenvectors, k): 28 | return eigenvectors[:, :k] 29 | 30 | # Step 6: Transform the original data to the new subspace 31 | def transform_data(X, components): 32 | return X.dot(components) 33 | 34 | # Function to perform PCA 35 | def pca(X, k): 36 | print(X[:10]) 37 | X_standardized = standardize_data(X) 38 | print(X_standardized[:10]) 39 | covariance_matrix = compute_covariance_matrix(X_standardized) 40 | print(covariance_matrix) 41 | eigenvalues, eigenvectors = eigen_decomposition(covariance_matrix) 42 | print(eigenvalues, eigenvectors) 43 | sorted_eigenvalues, sorted_eigenvectors = sort_eigenvalues_eigenvectors(eigenvalues, eigenvectors) 44 | top_k_components = select_top_k_components(sorted_eigenvectors, k) 45 | X_pca = transform_data(X_standardized, top_k_components) 46 | return X_pca 47 | 48 | 49 | def get_environment(config, value: str, env: str, error_msg: str) -> str: 50 | if value in config: 51 | token = config[value].value 52 | else: 53 | token = os.environ.get(env) 54 | if not token or token == "": 55 | raise Exception(error_msg) 56 | return token 57 | 58 | def get_token(env: str, default: str = None) -> str: 59 | # return token, but treat empty string als None 60 | token = tok if bool(tok := os.getenv(env, None)) else default 61 | return token -------------------------------------------------------------------------------- /goldenverba/server/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/goldenverba/server/__init__.py -------------------------------------------------------------------------------- /goldenverba/server/cli.py: -------------------------------------------------------------------------------- 1 | import click 2 | import uvicorn 3 | import os 4 | from dotenv import load_dotenv 5 | 6 | from goldenverba import verba_manager 7 | from goldenverba.server.types import Credentials 8 | 9 | load_dotenv() 10 | 11 | 12 | @click.group() 13 | def cli(): 14 | """Main command group for verba.""" 15 | pass 16 | 17 | 18 | @cli.command() 19 | @click.option( 20 | "--port", 21 | default=8000, 22 | help="FastAPI Port", 23 | ) 24 | @click.option( 25 | "--host", 26 | default="localhost", 27 | help="FastAPI Host", 28 | ) 29 | @click.option( 30 | "--prod/--no-prod", 31 | default=False, 32 | help="Run in production mode.", 33 | ) 34 | @click.option( 35 | "--workers", 36 | default=4, 37 | help="Workers to run Verba", 38 | ) 39 | def start(port, host, prod, workers): 40 | """ 41 | Run the FastAPI application. 42 | """ 43 | uvicorn.run( 44 | "goldenverba.server.api:app", 45 | host=host, 46 | port=port, 47 | reload=(not prod), 48 | workers=workers, 49 | ) 50 | 51 | 52 | @click.option( 53 | "--url", 54 | default=os.getenv("WEAVIATE_URL_VERBA"), 55 | help="Weaviate URL", 56 | ) 57 | @click.option( 58 | "--api_key", 59 | default=os.getenv("WEAVIATE_API_KEY_VERBA"), 60 | help="Weaviate API Key", 61 | ) 62 | @click.option( 63 | "--deployment", 64 | default="", 65 | help="Deployment (Local, Weaviate, Docker)", 66 | ) 67 | @click.option( 68 | "--full_reset", 69 | default=False, 70 | help="Full reset (True, False)", 71 | ) 72 | @cli.command() 73 | def reset(url, api_key, deployment, full_reset): 74 | """ 75 | Run the FastAPI application. 76 | """ 77 | import asyncio 78 | 79 | manager = verba_manager.VerbaManager() 80 | 81 | async def async_reset(): 82 | if url is not None and api_key is not None: 83 | if deployment == "" or deployment == "Weaviate": 84 | client = await manager.connect( 85 | Credentials(deployment="Weaviate", url=url, key=api_key) 86 | ) 87 | elif deployment == "Docker": 88 | client = await manager.connect( 89 | Credentials(deployment="Docker", url=url, key=api_key) 90 | ) 91 | else: 92 | raise ValueError("Invalid deployment") 93 | else: 94 | if deployment == "" or deployment == "Local": 95 | client = await manager.connect( 96 | Credentials(deployment="Local", url="", key="") 97 | ) 98 | else: 99 | raise ValueError("Invalid deployment") 100 | 101 | if not full_reset: 102 | await manager.reset_rag_config(client) 103 | await manager.reset_theme_config(client) 104 | await manager.reset_user_config(client) 105 | else: 106 | await manager.weaviate_manager.delete_all(client) 107 | 108 | await client.close() 109 | 110 | asyncio.run(async_reset()) 111 | 112 | 113 | if __name__ == "__main__": 114 | cli() 115 | -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/30i2FQTbR7Y4f-UfM6hbP/_buildManifest.js: -------------------------------------------------------------------------------- 1 | self.__BUILD_MANIFEST={__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/_error":["static/chunks/pages/_error-6ae619510b1539d6.js"],sortedPages:["/_app","/_error"]},self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB(); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/30i2FQTbR7Y4f-UfM6hbP/_ssgManifest.js: -------------------------------------------------------------------------------- 1 | self.__SSG_MANIFEST=new Set([]);self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB() -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/4ajn2kvxlVqvDvSUh7-up/_buildManifest.js: -------------------------------------------------------------------------------- 1 | self.__BUILD_MANIFEST={__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/_error":["static/chunks/pages/_error-6ae619510b1539d6.js"],sortedPages:["/_app","/_error"]},self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB(); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/4ajn2kvxlVqvDvSUh7-up/_ssgManifest.js: -------------------------------------------------------------------------------- 1 | self.__SSG_MANIFEST=new Set([]);self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB() -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/5piNIBwi9EVvWEGUCt1HJ/_buildManifest.js: -------------------------------------------------------------------------------- 1 | self.__BUILD_MANIFEST={__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/_error":["static/chunks/pages/_error-6ae619510b1539d6.js"],sortedPages:["/_app","/_error"]},self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB(); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/5piNIBwi9EVvWEGUCt1HJ/_ssgManifest.js: -------------------------------------------------------------------------------- 1 | self.__SSG_MANIFEST=new Set([]);self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB() -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/5rVRk1H0CSx_t9B72OCkV/_buildManifest.js: -------------------------------------------------------------------------------- 1 | self.__BUILD_MANIFEST={__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/_error":["static/chunks/pages/_error-6ae619510b1539d6.js"],sortedPages:["/_app","/_error"]},self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB(); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/5rVRk1H0CSx_t9B72OCkV/_ssgManifest.js: -------------------------------------------------------------------------------- 1 | self.__SSG_MANIFEST=new Set([]);self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB() -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/CZvV6ohXKOaM2HZQjSr_e/_buildManifest.js: -------------------------------------------------------------------------------- 1 | self.__BUILD_MANIFEST={__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/_error":["static/chunks/pages/_error-6ae619510b1539d6.js"],sortedPages:["/_app","/_error"]},self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB(); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/CZvV6ohXKOaM2HZQjSr_e/_ssgManifest.js: -------------------------------------------------------------------------------- 1 | self.__SSG_MANIFEST=new Set([]);self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB() -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/EK3SdW_8_2ZVH1NNgqlNv/_buildManifest.js: -------------------------------------------------------------------------------- 1 | self.__BUILD_MANIFEST={__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/_error":["static/chunks/pages/_error-6ae619510b1539d6.js"],sortedPages:["/_app","/_error"]},self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB(); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/EK3SdW_8_2ZVH1NNgqlNv/_ssgManifest.js: -------------------------------------------------------------------------------- 1 | self.__SSG_MANIFEST=new Set([]);self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB() -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/FEflRPdxwBXOroRwOpEz6/_buildManifest.js: -------------------------------------------------------------------------------- 1 | self.__BUILD_MANIFEST={__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/_error":["static/chunks/pages/_error-6ae619510b1539d6.js"],sortedPages:["/_app","/_error"]},self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB(); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/FEflRPdxwBXOroRwOpEz6/_ssgManifest.js: -------------------------------------------------------------------------------- 1 | self.__SSG_MANIFEST=new Set([]);self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB() -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/FcSX1HknjNhe9H0xxw_uy/_buildManifest.js: -------------------------------------------------------------------------------- 1 | self.__BUILD_MANIFEST={__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/_error":["static/chunks/pages/_error-6ae619510b1539d6.js"],sortedPages:["/_app","/_error"]},self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB(); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/FcSX1HknjNhe9H0xxw_uy/_ssgManifest.js: -------------------------------------------------------------------------------- 1 | self.__SSG_MANIFEST=new Set([]);self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB() -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/I01L2Qf2M5E8rKySVdfwz/_buildManifest.js: -------------------------------------------------------------------------------- 1 | self.__BUILD_MANIFEST={__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/_error":["static/chunks/pages/_error-6ae619510b1539d6.js"],sortedPages:["/_app","/_error"]},self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB(); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/I01L2Qf2M5E8rKySVdfwz/_ssgManifest.js: -------------------------------------------------------------------------------- 1 | self.__SSG_MANIFEST=new Set([]);self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB() -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/KoV36dmdEgYXG0yvTGe3m/_buildManifest.js: -------------------------------------------------------------------------------- 1 | self.__BUILD_MANIFEST={__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/_error":["static/chunks/pages/_error-6ae619510b1539d6.js"],sortedPages:["/_app","/_error"]},self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB(); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/KoV36dmdEgYXG0yvTGe3m/_ssgManifest.js: -------------------------------------------------------------------------------- 1 | self.__SSG_MANIFEST=new Set([]);self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB() -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/MYxb6oMzMgqonOwG97TqG/_buildManifest.js: -------------------------------------------------------------------------------- 1 | self.__BUILD_MANIFEST={__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/_error":["static/chunks/pages/_error-6ae619510b1539d6.js"],sortedPages:["/_app","/_error"]},self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB(); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/MYxb6oMzMgqonOwG97TqG/_ssgManifest.js: -------------------------------------------------------------------------------- 1 | self.__SSG_MANIFEST=new Set([]);self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB() -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/QPYBqPy_EgcZIfNhJUgzL/_buildManifest.js: -------------------------------------------------------------------------------- 1 | self.__BUILD_MANIFEST={__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/_error":["static/chunks/pages/_error-6ae619510b1539d6.js"],sortedPages:["/_app","/_error"]},self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB(); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/QPYBqPy_EgcZIfNhJUgzL/_ssgManifest.js: -------------------------------------------------------------------------------- 1 | self.__SSG_MANIFEST=new Set([]);self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB() -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/SqhqgckvG9-Sxn3_Nq2Rt/_buildManifest.js: -------------------------------------------------------------------------------- 1 | self.__BUILD_MANIFEST={__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/_error":["static/chunks/pages/_error-6ae619510b1539d6.js"],sortedPages:["/_app","/_error"]},self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB(); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/SqhqgckvG9-Sxn3_Nq2Rt/_ssgManifest.js: -------------------------------------------------------------------------------- 1 | self.__SSG_MANIFEST=new Set([]);self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB() -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/VZK8jRGqcSpcMf2ZOPpII/_buildManifest.js: -------------------------------------------------------------------------------- 1 | self.__BUILD_MANIFEST={__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/_error":["static/chunks/pages/_error-6ae619510b1539d6.js"],sortedPages:["/_app","/_error"]},self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB(); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/VZK8jRGqcSpcMf2ZOPpII/_ssgManifest.js: -------------------------------------------------------------------------------- 1 | self.__SSG_MANIFEST=new Set([]);self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB() -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/Y3oNq6sdVkiLcuMaChJwW/_buildManifest.js: -------------------------------------------------------------------------------- 1 | self.__BUILD_MANIFEST={__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/_error":["static/chunks/pages/_error-6ae619510b1539d6.js"],sortedPages:["/_app","/_error"]},self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB(); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/Y3oNq6sdVkiLcuMaChJwW/_ssgManifest.js: -------------------------------------------------------------------------------- 1 | self.__SSG_MANIFEST=new Set([]);self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB() -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/_LnFD6u1WPj3rRxWv1Mp3/_buildManifest.js: -------------------------------------------------------------------------------- 1 | self.__BUILD_MANIFEST={__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/_error":["static/chunks/pages/_error-6ae619510b1539d6.js"],sortedPages:["/_app","/_error"]},self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB(); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/_LnFD6u1WPj3rRxWv1Mp3/_ssgManifest.js: -------------------------------------------------------------------------------- 1 | self.__SSG_MANIFEST=new Set([]);self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB() -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/b8NLMEMd7UPwgQ6cqzdXK/_buildManifest.js: -------------------------------------------------------------------------------- 1 | self.__BUILD_MANIFEST={__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/_error":["static/chunks/pages/_error-6ae619510b1539d6.js"],sortedPages:["/_app","/_error"]},self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB(); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/b8NLMEMd7UPwgQ6cqzdXK/_ssgManifest.js: -------------------------------------------------------------------------------- 1 | self.__SSG_MANIFEST=new Set([]);self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB() -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/chunks/07115393-8a796b5d068e3710.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[682],{71375:function(t,a,n){n.d(a,{Lec:function(){return r},WMq:function(){return u}});var c=n(39350);function r(t){return(0,c.w_)({tag:"svg",attr:{viewBox:"0 0 24 24"},child:[{tag:"path",attr:{d:"M2 4.75C2 3.784 2.784 3 3.75 3h4.971c.58 0 1.12.286 1.447.765l1.404 2.063c.046.069.124.11.207.11h8.471c.966 0 1.75.783 1.75 1.75V19.25A1.75 1.75 0 0 1 20.25 21H3.75A1.75 1.75 0 0 1 2 19.25Z"}}]})(t)}function u(t){return(0,c.w_)({tag:"svg",attr:{viewBox:"0 0 24 24"},child:[{tag:"path",attr:{d:"M11.646 15.146 5.854 9.354a.5.5 0 0 1 .353-.854h11.586a.5.5 0 0 1 .353.854l-5.793 5.792a.5.5 0 0 1-.707 0Z"}}]})(t)}}}]); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/chunks/12038df7-bbbca262706a9194.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[400],{8603:function(t,c,n){n.d(c,{Lgw:function(){return h},OUD:function(){return a}});var r=n(39350);function a(t){return(0,r.w_)({tag:"svg",attr:{viewBox:"0 0 512 512"},child:[{tag:"path",attr:{d:"M435.9 64.9l-367.1 160c-6.5 3.1-6.3 12.4.3 15.3l99.3 56.1c5.9 3.3 13.2 2.6 18.3-1.8l195.8-168.8c1.3-1.1 4.4-3.2 5.6-2 1.3 1.3-.7 4.3-1.8 5.6L216.9 320.1c-4.7 5.3-5.4 13.1-1.6 19.1l64.9 104.1c3.2 6.3 12.3 6.2 15.2-.2L447.2 76c3.3-7.2-4.2-14.5-11.3-11.1z"}}]})(t)}function h(t){return(0,r.w_)({tag:"svg",attr:{viewBox:"0 0 512 512"},child:[{tag:"path",attr:{d:"M256 48C141.125 48 48 141.125 48 256s93.125 208 208 208 208-93.125 208-208S370.875 48 256 48zm107 229h-86v86h-42v-86h-86v-42h86v-86h42v86h86v42z"}}]})(t)}}}]); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/chunks/12038df7-bed05817827b4802.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[400],{8603:function(t,n,r){r.d(n,{Lgw:function(){return u},OUD:function(){return a},yQg:function(){return h}});var c=r(39350);function a(t){return(0,c.w_)({tag:"svg",attr:{viewBox:"0 0 512 512"},child:[{tag:"path",attr:{d:"M435.9 64.9l-367.1 160c-6.5 3.1-6.3 12.4.3 15.3l99.3 56.1c5.9 3.3 13.2 2.6 18.3-1.8l195.8-168.8c1.3-1.1 4.4-3.2 5.6-2 1.3 1.3-.7 4.3-1.8 5.6L216.9 320.1c-4.7 5.3-5.4 13.1-1.6 19.1l64.9 104.1c3.2 6.3 12.3 6.2 15.2-.2L447.2 76c3.3-7.2-4.2-14.5-11.3-11.1z"}}]})(t)}function u(t){return(0,c.w_)({tag:"svg",attr:{viewBox:"0 0 512 512"},child:[{tag:"path",attr:{d:"M256 48C141.125 48 48 141.125 48 256s93.125 208 208 208 208-93.125 208-208S370.875 48 256 48zm107 229h-86v86h-42v-86h-86v-42h86v-86h42v86h86v42z"}}]})(t)}function h(t){return(0,c.w_)({tag:"svg",attr:{viewBox:"0 0 512 512"},child:[{tag:"path",attr:{d:"M128 192l128 128 128-128z"}}]})(t)}}}]); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/chunks/39209d7c-1514aaef8caa025b.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[306],{54018:function(c,s,L){L.d(s,{vuX:function(){return l}});var t=L(39350);function l(c){return(0,t.w_)({tag:"svg",attr:{viewBox:"0 0 576 512"},child:[{tag:"path",attr:{d:"M234.7 42.7L197 56.8c-3 1.1-5 4-5 7.2s2 6.1 5 7.2l37.7 14.1L248.8 123c1.1 3 4 5 7.2 5s6.1-2 7.2-5l14.1-37.7L315 71.2c3-1.1 5-4 5-7.2s-2-6.1-5-7.2L277.3 42.7 263.2 5c-1.1-3-4-5-7.2-5s-6.1 2-7.2 5L234.7 42.7zM46.1 395.4c-18.7 18.7-18.7 49.1 0 67.9l34.6 34.6c18.7 18.7 49.1 18.7 67.9 0L529.9 116.5c18.7-18.7 18.7-49.1 0-67.9L495.3 14.1c-18.7-18.7-49.1-18.7-67.9 0L46.1 395.4zM484.6 82.6l-105 105-23.3-23.3 105-105 23.3 23.3zM7.5 117.2C3 118.9 0 123.2 0 128s3 9.1 7.5 10.8L64 160l21.2 56.5c1.7 4.5 6 7.5 10.8 7.5s9.1-3 10.8-7.5L128 160l56.5-21.2c4.5-1.7 7.5-6 7.5-10.8s-3-9.1-7.5-10.8L128 96 106.8 39.5C105.1 35 100.8 32 96 32s-9.1 3-10.8 7.5L64 96 7.5 117.2zm352 256c-4.5 1.7-7.5 6-7.5 10.8s3 9.1 7.5 10.8L416 416l21.2 56.5c1.7 4.5 6 7.5 10.8 7.5s9.1-3 10.8-7.5L480 416l56.5-21.2c4.5-1.7 7.5-6 7.5-10.8s-3-9.1-7.5-10.8L480 352l-21.2-56.5c-1.7-4.5-6-7.5-10.8-7.5s-9.1 3-10.8 7.5L416 352l-56.5 21.2z"}}]})(c)}}}]); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/chunks/39209d7c-9eeaeffa37c8b51e.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[306],{54018:function(t,c,a){a.d(c,{EQK:function(){return s}});var n=a(39350);function s(t){return(0,n.w_)({tag:"svg",attr:{viewBox:"0 0 512 512"},child:[{tag:"path",attr:{d:"M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM216 336h24V272H216c-13.3 0-24-10.7-24-24s10.7-24 24-24h48c13.3 0 24 10.7 24 24v88h8c13.3 0 24 10.7 24 24s-10.7 24-24 24H216c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-208a32 32 0 1 1 0 64 32 32 0 1 1 0-64z"}}]})(t)}}}]); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/chunks/39aecf79-474a3d3c48835c08.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[61],{21794:function(l,a,t){t.d(a,{drw:function(){return n},dvR:function(){return e}});var r=t(39350);function e(l){return(0,r.w_)({tag:"svg",attr:{viewBox:"0 0 24 24",fill:"currentColor","aria-hidden":"true"},child:[{tag:"path",attr:{fillRule:"evenodd",d:"M9 4.5a.75.75 0 01.721.544l.813 2.846a3.75 3.75 0 002.576 2.576l2.846.813a.75.75 0 010 1.442l-2.846.813a3.75 3.75 0 00-2.576 2.576l-.813 2.846a.75.75 0 01-1.442 0l-.813-2.846a3.75 3.75 0 00-2.576-2.576l-2.846-.813a.75.75 0 010-1.442l2.846-.813A3.75 3.75 0 007.466 7.89l.813-2.846A.75.75 0 019 4.5zM18 1.5a.75.75 0 01.728.568l.258 1.036c.236.94.97 1.674 1.91 1.91l1.036.258a.75.75 0 010 1.456l-1.036.258c-.94.236-1.674.97-1.91 1.91l-.258 1.036a.75.75 0 01-1.456 0l-.258-1.036a2.625 2.625 0 00-1.91-1.91l-1.036-.258a.75.75 0 010-1.456l1.036-.258a2.625 2.625 0 001.91-1.91l.258-1.036A.75.75 0 0118 1.5zM16.5 15a.75.75 0 01.712.513l.394 1.183c.15.447.5.799.948.948l1.183.395a.75.75 0 010 1.422l-1.183.395c-.447.15-.799.5-.948.948l-.395 1.183a.75.75 0 01-1.422 0l-.395-1.183a1.5 1.5 0 00-.948-.948l-1.183-.395a.75.75 0 010-1.422l1.183-.395c.447-.15.799-.5.948-.948l.395-1.183A.75.75 0 0116.5 15z",clipRule:"evenodd"}}]})(l)}function n(l){return(0,r.w_)({tag:"svg",attr:{viewBox:"0 0 20 20",fill:"currentColor","aria-hidden":"true"},child:[{tag:"path",attr:{d:"M15.98 1.804a1 1 0 00-1.96 0l-.24 1.192a1 1 0 01-.784.785l-1.192.238a1 1 0 000 1.962l1.192.238a1 1 0 01.785.785l.238 1.192a1 1 0 001.962 0l.238-1.192a1 1 0 01.785-.785l1.192-.238a1 1 0 000-1.962l-1.192-.238a1 1 0 01-.785-.785l-.238-1.192zM6.949 5.684a1 1 0 00-1.898 0l-.683 2.051a1 1 0 01-.633.633l-2.051.683a1 1 0 000 1.898l2.051.684a1 1 0 01.633.632l.683 2.051a1 1 0 001.898 0l.683-2.051a1 1 0 01.633-.633l2.051-.683a1 1 0 000-1.898l-2.051-.683a1 1 0 01-.633-.633L6.95 5.684zM13.949 13.684a1 1 0 00-1.898 0l-.184.551a1 1 0 01-.632.633l-.551.183a1 1 0 000 1.898l.551.183a1 1 0 01.633.633l.183.551a1 1 0 001.898 0l.184-.551a1 1 0 01.632-.633l.551-.183a1 1 0 000-1.898l-.551-.184a1 1 0 01-.633-.632l-.183-.551z"}}]})(l)}}}]); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/chunks/39aecf79-8d523cb23043db9d.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[61],{21794:function(l,a,e){e.d(a,{dvR:function(){return c}});var t=e(39350);function c(l){return(0,t.w_)({tag:"svg",attr:{viewBox:"0 0 24 24",fill:"currentColor","aria-hidden":"true"},child:[{tag:"path",attr:{fillRule:"evenodd",d:"M9 4.5a.75.75 0 01.721.544l.813 2.846a3.75 3.75 0 002.576 2.576l2.846.813a.75.75 0 010 1.442l-2.846.813a3.75 3.75 0 00-2.576 2.576l-.813 2.846a.75.75 0 01-1.442 0l-.813-2.846a3.75 3.75 0 00-2.576-2.576l-2.846-.813a.75.75 0 010-1.442l2.846-.813A3.75 3.75 0 007.466 7.89l.813-2.846A.75.75 0 019 4.5zM18 1.5a.75.75 0 01.728.568l.258 1.036c.236.94.97 1.674 1.91 1.91l1.036.258a.75.75 0 010 1.456l-1.036.258c-.94.236-1.674.97-1.91 1.91l-.258 1.036a.75.75 0 01-1.456 0l-.258-1.036a2.625 2.625 0 00-1.91-1.91l-1.036-.258a.75.75 0 010-1.456l1.036-.258a2.625 2.625 0 001.91-1.91l.258-1.036A.75.75 0 0118 1.5zM16.5 15a.75.75 0 01.712.513l.394 1.183c.15.447.5.799.948.948l1.183.395a.75.75 0 010 1.422l-1.183.395c-.447.15-.799.5-.948.948l-.395 1.183a.75.75 0 01-1.422 0l-.395-1.183a1.5 1.5 0 00-.948-.948l-1.183-.395a.75.75 0 010-1.422l1.183-.395c.447-.15.799-.5.948-.948l.395-1.183A.75.75 0 0116.5 15z",clipRule:"evenodd"}}]})(l)}}}]); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/chunks/472688b4-2c611c3f7f6780f5.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[370],{95183:function(t,s,c){c.d(s,{QQh:function(){return n}});var h=c(39350);function n(t){return(0,h.w_)({tag:"svg",attr:{version:"1.2",baseProfile:"tiny",viewBox:"0 0 24 24"},child:[{tag:"path",attr:{d:"M19 17h-14c-1.103 0-2 .897-2 2s.897 2 2 2h14c1.103 0 2-.897 2-2s-.897-2-2-2zM19 10h-14c-1.103 0-2 .897-2 2s.897 2 2 2h14c1.103 0 2-.897 2-2s-.897-2-2-2zM19 3h-14c-1.103 0-2 .897-2 2s.897 2 2 2h14c1.103 0 2-.897 2-2s-.897-2-2-2z"}}]})(t)}}}]); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/chunks/48507feb-c058e15125ba1e58.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[465],{25847:function(t,a,r){r.d(a,{FUn:function(){return h},Nwf:function(){return e},Y6Z:function(){return o}});var n=r(39350);function o(t){return(0,n.w_)({tag:"svg",attr:{viewBox:"0 0 24 24",strokeWidth:"2",stroke:"currentColor",fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},child:[{tag:"path",attr:{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}},{tag:"path",attr:{d:"M4 6c0 1.657 3.582 3 8 3s8 -1.343 8 -3s-3.582 -3 -8 -3s-8 1.343 -8 3"}},{tag:"path",attr:{d:"M4 6v6c0 1.657 3.582 3 8 3c.478 0 .947 -.016 1.402 -.046"}},{tag:"path",attr:{d:"M20 12v-6"}},{tag:"path",attr:{d:"M4 12v6c0 1.526 3.04 2.786 6.972 2.975"}},{tag:"path",attr:{d:"M18.42 15.61a2.1 2.1 0 0 1 2.97 2.97l-3.39 3.42h-3v-3l3.42 -3.39z"}}]})(t)}function e(t){return(0,n.w_)({tag:"svg",attr:{viewBox:"0 0 24 24",strokeWidth:"2",stroke:"currentColor",fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},child:[{tag:"path",attr:{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}},{tag:"path",attr:{d:"M7 12l5 5l-1.5 1.5a3.536 3.536 0 1 1 -5 -5l1.5 -1.5z"}},{tag:"path",attr:{d:"M17 12l-5 -5l1.5 -1.5a3.536 3.536 0 1 1 5 5l-1.5 1.5z"}},{tag:"path",attr:{d:"M3 21l2.5 -2.5"}},{tag:"path",attr:{d:"M18.5 5.5l2.5 -2.5"}},{tag:"path",attr:{d:"M10 11l-2 2"}},{tag:"path",attr:{d:"M13 14l-2 2"}}]})(t)}function h(t){return(0,n.w_)({tag:"svg",attr:{viewBox:"0 0 24 24",strokeWidth:"2",stroke:"currentColor",fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},child:[{tag:"path",attr:{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}},{tag:"path",attr:{d:"M10 4m0 1a1 1 0 0 1 1 -1h2a1 1 0 0 1 1 1v2a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1z"}},{tag:"path",attr:{d:"M3 17m0 1a1 1 0 0 1 1 -1h2a1 1 0 0 1 1 1v2a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1z"}},{tag:"path",attr:{d:"M17 17m0 1a1 1 0 0 1 1 -1h2a1 1 0 0 1 1 1v2a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1z"}},{tag:"path",attr:{d:"M6.5 17.1l5 -9.1"}},{tag:"path",attr:{d:"M17.5 17.1l-5 -9.1"}},{tag:"path",attr:{d:"M7 19l10 0"}}]})(t)}}}]); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/chunks/48507feb-cb362b7475ba2891.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[465],{25847:function(t,a,r){r.d(a,{FUn:function(){return o},Nwf:function(){return e}});var n=r(39350);function e(t){return(0,n.w_)({tag:"svg",attr:{viewBox:"0 0 24 24",strokeWidth:"2",stroke:"currentColor",fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},child:[{tag:"path",attr:{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}},{tag:"path",attr:{d:"M7 12l5 5l-1.5 1.5a3.536 3.536 0 1 1 -5 -5l1.5 -1.5z"}},{tag:"path",attr:{d:"M17 12l-5 -5l1.5 -1.5a3.536 3.536 0 1 1 5 5l-1.5 1.5z"}},{tag:"path",attr:{d:"M3 21l2.5 -2.5"}},{tag:"path",attr:{d:"M18.5 5.5l2.5 -2.5"}},{tag:"path",attr:{d:"M10 11l-2 2"}},{tag:"path",attr:{d:"M13 14l-2 2"}}]})(t)}function o(t){return(0,n.w_)({tag:"svg",attr:{viewBox:"0 0 24 24",strokeWidth:"2",stroke:"currentColor",fill:"none",strokeLinecap:"round",strokeLinejoin:"round"},child:[{tag:"path",attr:{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}},{tag:"path",attr:{d:"M10 4m0 1a1 1 0 0 1 1 -1h2a1 1 0 0 1 1 1v2a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1z"}},{tag:"path",attr:{d:"M3 17m0 1a1 1 0 0 1 1 -1h2a1 1 0 0 1 1 1v2a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1z"}},{tag:"path",attr:{d:"M17 17m0 1a1 1 0 0 1 1 -1h2a1 1 0 0 1 1 1v2a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1z"}},{tag:"path",attr:{d:"M6.5 17.1l5 -9.1"}},{tag:"path",attr:{d:"M17.5 17.1l-5 -9.1"}},{tag:"path",attr:{d:"M7 19l10 0"}}]})(t)}}}]); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/chunks/4f53ad1b-af82feddb1367bb5.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[636],{88033:function(C,t,l){l.d(t,{$Wy:function(){return n},ZWp:function(){return e}});var r=l(39350);function e(C){return(0,r.w_)({tag:"svg",attr:{viewBox:"0 0 24 24",fill:"none"},child:[{tag:"path",attr:{d:"M10 11C10 10.4477 10.4477 10 11 10H13C13.5523 10 14 10.4477 14 11C14 11.5523 13.5523 12 13 12H11C10.4477 12 10 11.5523 10 11Z",fill:"currentColor"}},{tag:"path",attr:{d:"M11 14C10.4477 14 10 14.4477 10 15C10 15.5523 10.4477 16 11 16H13C13.5523 16 14 15.5523 14 15C14 14.4477 13.5523 14 13 14H11Z",fill:"currentColor"}},{tag:"path",attr:{fillRule:"evenodd",clipRule:"evenodd",d:"M9.09447 4.74918C8.41606 4.03243 8 3.0648 8 2H10C10 3.10457 10.8954 4 12 4C13.1046 4 14 3.10457 14 2H16C16 3.0648 15.5839 4.03243 14.9055 4.74918C16.1782 5.45491 17.1673 6.6099 17.6586 8H19C19.5523 8 20 8.44772 20 9C20 9.55229 19.5523 10 19 10H18V12H19C19.5523 12 20 12.4477 20 13C20 13.5523 19.5523 14 19 14H18V16H19C19.5523 16 20 16.4477 20 17C20 17.5523 19.5523 18 19 18H17.6586C16.8349 20.3304 14.6124 22 12 22C9.38756 22 7.16508 20.3304 6.34141 18H5C4.44772 18 4 17.5523 4 17C4 16.4477 4.44772 16 5 16H6V14H5C4.44772 14 4 13.5523 4 13C4 12.4477 4.44772 12 5 12H6V10H5C4.44772 10 4 9.55229 4 9C4 8.44772 4.44772 8 5 8H6.34141C6.83274 6.6099 7.82181 5.45491 9.09447 4.74918ZM8 16V10C8 7.79086 9.79086 6 12 6C14.2091 6 16 7.79086 16 10V16C16 18.2091 14.2091 20 12 20C9.79086 20 8 18.2091 8 16Z",fill:"currentColor"}}]})(C)}function n(C){return(0,r.w_)({tag:"svg",attr:{viewBox:"0 0 24 24",fill:"none"},child:[{tag:"path",attr:{fillRule:"evenodd",clipRule:"evenodd",d:"M14 7C13.4477 7 13 7.44772 13 8V16C13 16.5523 13.4477 17 14 17H18C18.5523 17 19 16.5523 19 16V8C19 7.44772 18.5523 7 18 7H14ZM17 9H15V15H17V9Z",fill:"currentColor"}},{tag:"path",attr:{d:"M6 7C5.44772 7 5 7.44772 5 8C5 8.55228 5.44772 9 6 9H10C10.5523 9 11 8.55228 11 8C11 7.44772 10.5523 7 10 7H6Z",fill:"currentColor"}},{tag:"path",attr:{d:"M6 11C5.44772 11 5 11.4477 5 12C5 12.5523 5.44772 13 6 13H10C10.5523 13 11 12.5523 11 12C11 11.4477 10.5523 11 10 11H6Z",fill:"currentColor"}},{tag:"path",attr:{d:"M5 16C5 15.4477 5.44772 15 6 15H10C10.5523 15 11 15.4477 11 16C11 16.5523 10.5523 17 10 17H6C5.44772 17 5 16.5523 5 16Z",fill:"currentColor"}},{tag:"path",attr:{fillRule:"evenodd",clipRule:"evenodd",d:"M4 3C2.34315 3 1 4.34315 1 6V18C1 19.6569 2.34315 21 4 21H20C21.6569 21 23 19.6569 23 18V6C23 4.34315 21.6569 3 20 3H4ZM20 5H4C3.44772 5 3 5.44772 3 6V18C3 18.5523 3.44772 19 4 19H20C20.5523 19 21 18.5523 21 18V6C21 5.44772 20.5523 5 20 5Z",fill:"currentColor"}}]})(C)}}}]); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/chunks/4f53ad1b-cf02b0f93cf25527.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[636],{88033:function(C,t,l){l.d(t,{ZWp:function(){return e}});var r=l(39350);function e(C){return(0,r.w_)({tag:"svg",attr:{viewBox:"0 0 24 24",fill:"none"},child:[{tag:"path",attr:{d:"M10 11C10 10.4477 10.4477 10 11 10H13C13.5523 10 14 10.4477 14 11C14 11.5523 13.5523 12 13 12H11C10.4477 12 10 11.5523 10 11Z",fill:"currentColor"}},{tag:"path",attr:{d:"M11 14C10.4477 14 10 14.4477 10 15C10 15.5523 10.4477 16 11 16H13C13.5523 16 14 15.5523 14 15C14 14.4477 13.5523 14 13 14H11Z",fill:"currentColor"}},{tag:"path",attr:{fillRule:"evenodd",clipRule:"evenodd",d:"M9.09447 4.74918C8.41606 4.03243 8 3.0648 8 2H10C10 3.10457 10.8954 4 12 4C13.1046 4 14 3.10457 14 2H16C16 3.0648 15.5839 4.03243 14.9055 4.74918C16.1782 5.45491 17.1673 6.6099 17.6586 8H19C19.5523 8 20 8.44772 20 9C20 9.55229 19.5523 10 19 10H18V12H19C19.5523 12 20 12.4477 20 13C20 13.5523 19.5523 14 19 14H18V16H19C19.5523 16 20 16.4477 20 17C20 17.5523 19.5523 18 19 18H17.6586C16.8349 20.3304 14.6124 22 12 22C9.38756 22 7.16508 20.3304 6.34141 18H5C4.44772 18 4 17.5523 4 17C4 16.4477 4.44772 16 5 16H6V14H5C4.44772 14 4 13.5523 4 13C4 12.4477 4.44772 12 5 12H6V10H5C4.44772 10 4 9.55229 4 9C4 8.44772 4.44772 8 5 8H6.34141C6.83274 6.6099 7.82181 5.45491 9.09447 4.74918ZM8 16V10C8 7.79086 9.79086 6 12 6C14.2091 6 16 7.79086 16 10V16C16 18.2091 14.2091 20 12 20C9.79086 20 8 18.2091 8 16Z",fill:"currentColor"}}]})(C)}}}]); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/chunks/4f9d9cd8-7217d0ac0bfcc7ce.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[929],{22034:function(t,n,C){C.d(n,{Xn2:function(){return a}});var u=C(39350);function a(t){return(0,u.w_)({tag:"svg",attr:{viewBox:"0 0 24 24"},child:[{tag:"path",attr:{d:"M12 14V22H4C4 17.5817 7.58172 14 12 14ZM12 13C8.685 13 6 10.315 6 7C6 3.685 8.685 1 12 1C15.315 1 18 3.685 18 7C18 10.315 15.315 13 12 13ZM21 17H22V22H14V17H15V16C15 14.3431 16.3431 13 18 13C19.6569 13 21 14.3431 21 16V17ZM19 17V16C19 15.4477 18.5523 15 18 15C17.4477 15 17 15.4477 17 16V17H19Z"}}]})(t)}}}]); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/chunks/5349c568-e26f968c6773abca.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[520],{67447:function(l,t,h){h.d(t,{HL_:function(){return r}});var n=h(39350);function r(l){return(0,n.w_)({tag:"svg",attr:{viewBox:"0 0 16 16",fill:"currentColor"},child:[{tag:"path",attr:{d:"M14.85 2.65l-1.5-1.5L13 1H4.48l-.5.5V4H1.5l-.5.5v10l.5.5h10l.5-.5V12h2.5l.5-.5V3l-.15-.35zM11 14H2V5h1v3.07h6V5h.79L11 6.21V14zM6 7V5h2v2H6zm8 4h-2V6l-.15-.35-1.5-1.5L10 4H5V2h7.81l1.21 1.21L14 11z"}}]})(l)}}}]); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/chunks/737dfa3e-71fd4aa07f7d84a6.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[33],{97223:function(t,n,e){e.d(n,{bqP:function(){return i}});var r=e(39350);function i(t){return(0,r.w_)({tag:"svg",attr:{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"},child:[{tag:"line",attr:{x1:"4",x2:"20",y1:"12",y2:"12"}},{tag:"line",attr:{x1:"4",x2:"20",y1:"6",y2:"6"}},{tag:"line",attr:{x1:"4",x2:"20",y1:"18",y2:"18"}}]})(t)}}}]); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/chunks/8dc5345f-9a36b2be5ef7459c.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[115],{93850:function(t,a,h){h.d(a,{I2T:function(){return r},N3m:function(){return c}});var n=h(39350);function r(t){return(0,n.w_)({tag:"svg",attr:{viewBox:"0 0 24 24"},child:[{tag:"path",attr:{d:"M11.001 10h2v5h-2zM11 16h2v2h-2z"}},{tag:"path",attr:{d:"M13.768 4.2C13.42 3.545 12.742 3.138 12 3.138s-1.42.407-1.768 1.063L2.894 18.064a1.986 1.986 0 0 0 .054 1.968A1.984 1.984 0 0 0 4.661 21h14.678c.708 0 1.349-.362 1.714-.968a1.989 1.989 0 0 0 .054-1.968L13.768 4.2zM4.661 19 12 5.137 19.344 19H4.661z"}}]})(t)}function c(t){return(0,n.w_)({tag:"svg",attr:{viewBox:"0 0 24 24"},child:[{tag:"path",attr:{d:"M20 2H4c-1.103 0-2 .897-2 2v18l4-4h14c1.103 0 2-.897 2-2V4c0-1.103-.897-2-2-2zm-7 13h-2v-2h2v2zm0-4h-2V5h2v6z"}}]})(t)}}}]); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/chunks/8dc5345f-dfd13b91b6647830.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[115],{93850:function(t,h,a){a.d(h,{I2T:function(){return r},N3m:function(){return c},hCA:function(){return u},yZ3:function(){return v}});var n=a(39350);function r(t){return(0,n.w_)({tag:"svg",attr:{viewBox:"0 0 24 24"},child:[{tag:"path",attr:{d:"M11.001 10h2v5h-2zM11 16h2v2h-2z"}},{tag:"path",attr:{d:"M13.768 4.2C13.42 3.545 12.742 3.138 12 3.138s-1.42.407-1.768 1.063L2.894 18.064a1.986 1.986 0 0 0 .054 1.968A1.984 1.984 0 0 0 4.661 21h14.678c.708 0 1.349-.362 1.714-.968a1.989 1.989 0 0 0 .054-1.968L13.768 4.2zM4.661 19 12 5.137 19.344 19H4.661z"}}]})(t)}function c(t){return(0,n.w_)({tag:"svg",attr:{viewBox:"0 0 24 24"},child:[{tag:"path",attr:{d:"M20 2H4c-1.103 0-2 .897-2 2v18l4-4h14c1.103 0 2-.897 2-2V4c0-1.103-.897-2-2-2zm-7 13h-2v-2h2v2zm0-4h-2V5h2v6z"}}]})(t)}function v(t){return(0,n.w_)({tag:"svg",attr:{viewBox:"0 0 24 24"},child:[{tag:"path",attr:{d:"M11.953 2C6.465 2 2 6.486 2 12s4.486 10 10 10 10-4.486 10-10S17.493 2 11.953 2zM13 17h-2v-2h2v2zm0-4h-2V7h2v6z"}}]})(t)}function u(t){return(0,n.w_)({tag:"svg",attr:{viewBox:"0 0 24 24"},child:[{tag:"path",attr:{d:"m8.5 18 3.5 4 3.5-4H19c1.103 0 2-.897 2-2V4c0-1.103-.897-2-2-2H5c-1.103 0-2 .897-2 2v12c0 1.103.897 2 2 2h3.5zM7 7h10v2H7V7zm0 4h7v2H7v-2z"}}]})(t)}}}]); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/chunks/8e68d877-65c524a5e56473c0.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[652],{73207:function(t,n,e){e.d(n,{y4s:function(){return C}});var r=e(39350);function C(t){return(0,r.w_)({tag:"svg",attr:{viewBox:"0 0 24 24"},child:[{tag:"path",attr:{fill:"none",stroke:"#000",strokeWidth:"2",d:"M10,21 C7.50000053,23.5 5.00000002,23 3,21 C0.999999977,19 0.500000114,16.5 3.00000004,14 C5.49999997,11.5 5.99999998,11 5.99999998,11 L13.0000005,18 C13.0000005,18 12.4999995,18.5 10,21 Z M14.0003207,3 C16.5,0.499999776 19,0.999999776 21.001068,3 C23.002136,5.00000022 23.5,7.49999978 21.001068,10 C18.5021359,12.5000002 18.0007478,13 18.0007478,13 L11,6 C11,6 11.5006414,5.50000022 14.0003207,3 Z M11,9.9999 L8.5,12.4999999 L11,9.9999 Z M14,13 L11.5,15.5 L14,13 Z"}}]})(t)}}}]); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/chunks/app/_not-found/page-26d6c07435b6028b.js: -------------------------------------------------------------------------------- 1 | (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[409],{67589:function(e,t,n){(window.__NEXT_P=window.__NEXT_P||[]).push(["/_not-found/page",function(){return n(35457)}])},35457:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return s}}),n(99920);let i=n(57437);n(2265);let o={fontFamily:'system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji"',height:"100vh",textAlign:"center",display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center"},l={display:"inline-block"},r={display:"inline-block",margin:"0 20px 0 0",padding:"0 23px 0 0",fontSize:24,fontWeight:500,verticalAlign:"top",lineHeight:"49px"},d={fontSize:14,fontWeight:400,lineHeight:"49px",margin:0};function s(){return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)("title",{children:"404: This page could not be found."}),(0,i.jsx)("div",{style:o,children:(0,i.jsxs)("div",{children:[(0,i.jsx)("style",{dangerouslySetInnerHTML:{__html:"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}),(0,i.jsx)("h1",{className:"next-error-h1",style:r,children:"404"}),(0,i.jsx)("div",{style:l,children:(0,i.jsx)("h2",{style:d,children:"This page could not be found."})})]})})]})}("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),e.exports=t.default)}},function(e){e.O(0,[971,23,744],function(){return e(e.s=67589)}),_N_E=e.O()}]); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/chunks/app/_not-found/page-aaadc9fa354a98b4.js: -------------------------------------------------------------------------------- 1 | (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[409],{67589:function(e,t,n){(window.__NEXT_P=window.__NEXT_P||[]).push(["/_not-found/page",function(){return n(35457)}])},35457:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return s}}),n(99920);let i=n(57437);n(2265);let o={fontFamily:'system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji"',height:"100vh",textAlign:"center",display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center"},l={display:"inline-block"},r={display:"inline-block",margin:"0 20px 0 0",padding:"0 23px 0 0",fontSize:24,fontWeight:500,verticalAlign:"top",lineHeight:"49px"},d={fontSize:14,fontWeight:400,lineHeight:"49px",margin:0};function s(){return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)("title",{children:"404: This page could not be found."}),(0,i.jsx)("div",{style:o,children:(0,i.jsxs)("div",{children:[(0,i.jsx)("style",{dangerouslySetInnerHTML:{__html:"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}),(0,i.jsx)("h1",{className:"next-error-h1",style:r,children:"404"}),(0,i.jsx)("div",{style:l,children:(0,i.jsx)("h2",{style:d,children:"This page could not be found."})})]})})]})}("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),e.exports=t.default)}},function(e){e.O(0,[971,23,744],function(){return e(e.s=67589)}),_N_E=e.O()}]); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/chunks/app/layout-ad434663ed5b1d3a.js: -------------------------------------------------------------------------------- 1 | (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[185],{6458:function(n,e,u){Promise.resolve().then(u.t.bind(u,58877,23))},58877:function(){}},function(n){n.O(0,[404,971,23,744],function(){return n(n.s=6458)}),_N_E=n.O()}]); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/chunks/bc9c3264-007b030a3d8b973f.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[582],{65125:function(t,n,a){a.d(n,{B4e:function(){return e},Ffb:function(){return v},Fqs:function(){return c},Vqr:function(){return i},vVM:function(){return r}});var h=a(39350);function r(t){return(0,h.w_)({tag:"svg",attr:{viewBox:"0 0 24 24"},child:[{tag:"path",attr:{fill:"none",d:"M0 0h24v24H0z"}},{tag:"path",attr:{d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"}}]})(t)}function c(t){return(0,h.w_)({tag:"svg",attr:{viewBox:"0 0 24 24"},child:[{tag:"path",attr:{fill:"none",d:"M0 0h24v24H0z"}},{tag:"path",attr:{d:"M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"}}]})(t)}function i(t){return(0,h.w_)({tag:"svg",attr:{viewBox:"0 0 24 24"},child:[{tag:"path",attr:{fill:"none",d:"M0 0h24v24H0z"}},{tag:"path",attr:{d:"M19 2h-4.18C14.4.84 13.3 0 12 0c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm7 18H5V4h2v3h10V4h2v16z"}}]})(t)}function e(t){return(0,h.w_)({tag:"svg",attr:{viewBox:"0 0 24 24"},child:[{tag:"path",attr:{fill:"none",d:"M0 0h24v24H0z"}},{tag:"path",attr:{d:"M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z"}}]})(t)}function v(t){return(0,h.w_)({tag:"svg",attr:{viewBox:"0 0 24 24"},child:[{tag:"path",attr:{fill:"none",d:"M0 0h24v24H0V0z"}},{tag:"path",attr:{d:"M17.65 6.35A7.958 7.958 0 0012 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08A5.99 5.99 0 0112 18c-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"}}]})(t)}}}]); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/chunks/ec3863c0-3299d7812f924fb2.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[190],{58177:function(t,a,r){r.d(a,{$Kz:function(){return u},A$d:function(){return e},Kth:function(){return n},VOs:function(){return v},emU:function(){return i},p$f:function(){return l},utr:function(){return c},zfW:function(){return o}});var h=r(39350);function n(t){return(0,h.w_)({tag:"svg",attr:{viewBox:"0 0 512 512"},child:[{tag:"path",attr:{d:"M256 48C141.31 48 48 141.31 48 256s93.31 208 208 208 208-93.31 208-208S370.69 48 256 48zm96 224h-80v80h-32v-80h-80v-32h80v-80h32v80h80z"}}]})(t)}function c(t){return(0,h.w_)({tag:"svg",attr:{viewBox:"0 0 512 512"},child:[{tag:"path",attr:{d:"M475.22 206.52c-10.34-48.65-37.76-92.93-77.22-124.68A227.4 227.4 0 00255.82 32C194.9 32 138 55.47 95.46 98.09 54.35 139.33 31.82 193.78 32 251.37a215.66 215.66 0 0035.65 118.76l4.35 6.05L48 480l114.8-28.56s2.3.77 4 1.42 16.33 6.26 31.85 10.6c12.9 3.6 39.74 9 60.77 9 59.65 0 115.35-23.1 156.83-65.06C457.36 365.77 480 310.42 480 251.49a213.5 213.5 0 00-4.78-44.97z"}}]})(t)}function i(t){return(0,h.w_)({tag:"svg",attr:{viewBox:"0 0 512 512"},child:[{tag:"path",attr:{d:"M240 216V32H92a12 12 0 00-12 12v424a12 12 0 0012 12h328a12 12 0 0012-12V224H248a8 8 0 01-8-8z"}},{tag:"path",attr:{d:"M272 41.69V188a4 4 0 004 4h146.31a2 2 0 001.42-3.41L275.41 40.27a2 2 0 00-3.41 1.42z"}}]})(t)}function l(t){return(0,h.w_)({tag:"svg",attr:{viewBox:"0 0 512 512"},child:[{tag:"path",attr:{d:"M160 240h160V96a16 16 0 00-16-16H64a16 16 0 00-16 16v320a16 16 0 0016 16h240a16 16 0 0016-16V272H160zm299.31 4.69L368 153.37 345.37 176l64 64H320v32h89.37l-64 64L368 358.63l91.31-91.32a16 16 0 000-22.62z"}}]})(t)}function u(t){return(0,h.w_)({tag:"svg",attr:{viewBox:"0 0 512 512"},child:[{tag:"path",attr:{d:"M439.91 112h-23.82a.09.09 0 00-.09.09V416a32 32 0 0032 32 32 32 0 0032-32V152.09A40.09 40.09 0 00439.91 112z"}},{tag:"path",attr:{d:"M384 416V72a40 40 0 00-40-40H72a40 40 0 00-40 40v352a56 56 0 0056 56h342.85a1.14 1.14 0 001.15-1.15 1.14 1.14 0 00-.85-1.1A64.11 64.11 0 01384 416zM96 128a16 16 0 0116-16h64a16 16 0 0116 16v64a16 16 0 01-16 16h-64a16 16 0 01-16-16zm208 272H112.45c-8.61 0-16-6.62-16.43-15.23A16 16 0 01112 368h191.55c8.61 0 16 6.62 16.43 15.23A16 16 0 01304 400zm0-64H112.45c-8.61 0-16-6.62-16.43-15.23A16 16 0 01112 304h191.55c8.61 0 16 6.62 16.43 15.23A16 16 0 01304 336zm0-64H112.45c-8.61 0-16-6.62-16.43-15.23A16 16 0 01112 240h191.55c8.61 0 16 6.62 16.43 15.23A16 16 0 01304 272zm0-64h-63.55c-8.61 0-16-6.62-16.43-15.23A16 16 0 01240 176h63.55c8.61 0 16 6.62 16.43 15.23A16 16 0 01304 208zm0-64h-63.55c-8.61 0-16-6.62-16.43-15.23A16 16 0 01240 112h63.55c8.61 0 16 6.62 16.43 15.23A16 16 0 01304 144z"}}]})(t)}function e(t){return(0,h.w_)({tag:"svg",attr:{viewBox:"0 0 512 512"},child:[{tag:"path",attr:{fill:"none",strokeLinecap:"round",strokeMiterlimit:"10",strokeWidth:"32",d:"M400 148l-21.12-24.57A191.43 191.43 0 00240 64C134 64 48 150 48 256s86 192 192 192a192.09 192.09 0 00181.07-128"}},{tag:"path",attr:{d:"M464 97.42V208a16 16 0 01-16 16H337.42c-14.26 0-21.4-17.23-11.32-27.31L436.69 86.1C446.77 76 464 83.16 464 97.42z"}}]})(t)}function o(t){return(0,h.w_)({tag:"svg",attr:{viewBox:"0 0 512 512"},child:[{tag:"path",attr:{d:"M256 176a80 80 0 1080 80 80.24 80.24 0 00-80-80zm172.72 80a165.53 165.53 0 01-1.64 22.34l48.69 38.12a11.59 11.59 0 012.63 14.78l-46.06 79.52a11.64 11.64 0 01-14.14 4.93l-57.25-23a176.56 176.56 0 01-38.82 22.67l-8.56 60.78a11.93 11.93 0 01-11.51 9.86h-92.12a12 12 0 01-11.51-9.53l-8.56-60.78A169.3 169.3 0 01151.05 393L93.8 416a11.64 11.64 0 01-14.14-4.92L33.6 331.57a11.59 11.59 0 012.63-14.78l48.69-38.12A174.58 174.58 0 0183.28 256a165.53 165.53 0 011.64-22.34l-48.69-38.12a11.59 11.59 0 01-2.63-14.78l46.06-79.52a11.64 11.64 0 0114.14-4.93l57.25 23a176.56 176.56 0 0138.82-22.67l8.56-60.78A11.93 11.93 0 01209.94 26h92.12a12 12 0 0111.51 9.53l8.56 60.78A169.3 169.3 0 01361 119l57.2-23a11.64 11.64 0 0114.14 4.92l46.06 79.52a11.59 11.59 0 01-2.63 14.78l-48.69 38.12a174.58 174.58 0 011.64 22.66z"}}]})(t)}function v(t){return(0,h.w_)({tag:"svg",attr:{viewBox:"0 0 512 512"},child:[{tag:"path",attr:{fill:"none",d:"M296 64h-80a7.91 7.91 0 00-8 8v24h96V72a7.91 7.91 0 00-8-8z"}},{tag:"path",attr:{d:"M432 96h-96V72a40 40 0 00-40-40h-80a40 40 0 00-40 40v24H80a16 16 0 000 32h17l19 304.92c1.42 26.85 22 47.08 48 47.08h184c26.13 0 46.3-19.78 48-47l19-305h17a16 16 0 000-32zM192.57 416H192a16 16 0 01-16-15.43l-8-224a16 16 0 1132-1.14l8 224A16 16 0 01192.57 416zM272 400a16 16 0 01-32 0V176a16 16 0 0132 0zm32-304h-96V72a7.91 7.91 0 018-8h80a7.91 7.91 0 018 8zm32 304.57A16 16 0 01320 416h-.58A16 16 0 01304 399.43l8-224a16 16 0 1132 1.14z"}}]})(t)}}}]); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/chunks/main-app-6d8fe3bc29305481.js: -------------------------------------------------------------------------------- 1 | (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[744],{16878:function(e,n,t){Promise.resolve().then(t.t.bind(t,95751,23)),Promise.resolve().then(t.t.bind(t,66513,23)),Promise.resolve().then(t.t.bind(t,76130,23)),Promise.resolve().then(t.t.bind(t,39275,23)),Promise.resolve().then(t.t.bind(t,16585,23)),Promise.resolve().then(t.t.bind(t,61343,23))}},function(e){var n=function(n){return e(e.s=n)};e.O(0,[971,23],function(){return n(11028),n(16878)}),_N_E=e.O()}]); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/chunks/pages/_app-037b5d058bd9a820.js: -------------------------------------------------------------------------------- 1 | (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[888],{41597:function(n,_,u){(window.__NEXT_P=window.__NEXT_P||[]).push(["/_app",function(){return u(52239)}])}},function(n){var _=function(_){return n(n.s=_)};n.O(0,[774,179],function(){return _(41597),_(26036)}),_N_E=n.O()}]); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/chunks/pages/_error-6ae619510b1539d6.js: -------------------------------------------------------------------------------- 1 | (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[820],{81981:function(n,_,u){(window.__NEXT_P=window.__NEXT_P||[]).push(["/_error",function(){return u(83387)}])}},function(n){n.O(0,[888,774,179],function(){return n(n.s=81981)}),_N_E=n.O()}]); -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/_next/static/chunks/webpack-e6d8fc8882b3cc5a.js: -------------------------------------------------------------------------------- 1 | !function(){"use strict";var t,e,n,r,o,u,i,c,f,a={},l={};function s(t){var e=l[t];if(void 0!==e)return e.exports;var n=l[t]={exports:{}},r=!0;try{a[t].call(n.exports,n,n.exports,s),r=!1}finally{r&&delete l[t]}return n.exports}s.m=a,t=[],s.O=function(e,n,r,o){if(n){o=o||0;for(var u=t.length;u>0&&t[u-1][2]>o;u--)t[u]=t[u-1];t[u]=[n,r,o];return}for(var i=1/0,u=0;u=o&&Object.keys(s.O).every(function(t){return s.O[t](n[f])})?n.splice(f--,1):(c=!1,o -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/shaders/includes/simplexNoise4d.glsl: -------------------------------------------------------------------------------- 1 | // Simplex 4D Noise 2 | // by Ian McEwan, Ashima Arts 3 | // 4 | vec4 permute(vec4 x){return mod(((x*34.0)+1.0)*x, 289.0);} 5 | float permute(float x){return floor(mod(((x*34.0)+1.0)*x, 289.0));} 6 | vec4 taylorInvSqrt(vec4 r){return 1.79284291400159 - 0.85373472095314 * r;} 7 | float taylorInvSqrt(float r){return 1.79284291400159 - 0.85373472095314 * r;} 8 | 9 | vec4 grad4(float j, vec4 ip) 10 | { 11 | const vec4 ones = vec4(1.0, 1.0, 1.0, -1.0); 12 | vec4 p,s; 13 | 14 | p.xyz = floor( fract (vec3(j) * ip.xyz) * 7.0) * ip.z - 1.0; 15 | p.w = 1.5 - dot(abs(p.xyz), ones.xyz); 16 | s = vec4(lessThan(p, vec4(0.0))); 17 | p.xyz = p.xyz + (s.xyz*2.0 - 1.0) * s.www; 18 | 19 | return p; 20 | 21 | 22 | float simplexNoise4d(vec4 v) 23 | { 24 | const vec2 C = vec2( 0.138196601125010504, // (5 - sqrt(5))/20 G4 25 | 0.309016994374947451); // (sqrt(5) - 1)/4 F4 26 | // First corner 27 | vec4 i = floor(v + dot(v, C.yyyy) ); 28 | vec4 x0 = v - i + dot(i, C.xxxx); 29 | 30 | // Other corners 31 | 32 | // Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI) 33 | vec4 i0; 34 | 35 | vec3 isX = step( x0.yzw, x0.xxx ); 36 | vec3 isYZ = step( x0.zww, x0.yyz ); 37 | // i0.x = dot( isX, vec3( 1.0 ) ); 38 | i0.x = isX.x + isX.y + isX.z; 39 | i0.yzw = 1.0 - isX; 40 | 41 | // i0.y += dot( isYZ.xy, vec2( 1.0 ) ); 42 | i0.y += isYZ.x + isYZ.y; 43 | i0.zw += 1.0 - isYZ.xy; 44 | 45 | i0.z += isYZ.z; 46 | i0.w += 1.0 - isYZ.z; 47 | 48 | // i0 now contains the unique values 0,1,2,3 in each channel 49 | vec4 i3 = clamp( i0, 0.0, 1.0 ); 50 | vec4 i2 = clamp( i0-1.0, 0.0, 1.0 ); 51 | vec4 i1 = clamp( i0-2.0, 0.0, 1.0 ); 52 | 53 | // x0 = x0 - 0.0 + 0.0 * C 54 | vec4 x1 = x0 - i1 + 1.0 * C.xxxx; 55 | vec4 x2 = x0 - i2 + 2.0 * C.xxxx; 56 | vec4 x3 = x0 - i3 + 3.0 * C.xxxx; 57 | vec4 x4 = x0 - 1.0 + 4.0 * C.xxxx; 58 | 59 | // Permutations 60 | i = mod(i, 289.0); 61 | float j0 = permute( permute( permute( permute(i.w) + i.z) + i.y) + i.x); 62 | vec4 j1 = permute( permute( permute( permute ( 63 | i.w + vec4(i1.w, i2.w, i3.w, 1.0 )) 64 | + i.z + vec4(i1.z, i2.z, i3.z, 1.0 )) 65 | + i.y + vec4(i1.y, i2.y, i3.y, 1.0 )) 66 | + i.x + vec4(i1.x, i2.x, i3.x, 1.0 )); 67 | // Gradients 68 | // ( 7*7*6 points uniformly over a cube, mapped onto a 4-octahedron.) 69 | // 7*7*6 = 294, which is close to the ring size 17*17 = 289. 70 | 71 | vec4 ip = vec4(1.0/294.0, 1.0/49.0, 1.0/7.0, 0.0) ; 72 | 73 | vec4 p0 = grad4(j0, ip); 74 | vec4 p1 = grad4(j1.x, ip); 75 | vec4 p2 = grad4(j1.y, ip); 76 | vec4 p3 = grad4(j1.z, ip); 77 | vec4 p4 = grad4(j1.w, ip); 78 | 79 | // Normalise gradients 80 | vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3))); 81 | p0 *= norm.x; 82 | p1 *= norm.y; 83 | p2 *= norm.z; 84 | p3 *= norm.w; 85 | p4 *= taylorInvSqrt(dot(p4,p4)); 86 | 87 | // Mix contributions from the five corners 88 | vec3 m0 = max(0.6 - vec3(dot(x0,x0), dot(x1,x1), dot(x2,x2)), 0.0); 89 | vec2 m1 = max(0.6 - vec2(dot(x3,x3), dot(x4,x4) ), 0.0); 90 | m0 = m0 * m0; 91 | m1 = m1 * m1; 92 | return 49.0 * ( dot(m0*m0, vec3( dot( p0, x0 ), dot( p1, x1 ), dot( p2, x2 ))) 93 | + dot(m1*m1, vec2( dot( p3, x3 ), dot( p4, x4 ) ) ) ) ; 94 | 95 | } -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/shaders/wobble/fragment.glsl: -------------------------------------------------------------------------------- 1 | varying float vWobble; 2 | uniform vec3 uColorA; 3 | uniform vec3 uColorB; 4 | 5 | void main() 6 | { 7 | float colorMix = smoothstep(-1.0, 1.0, vWobble); 8 | csm_DiffuseColor.rgb = mix(uColorA, uColorB, colorMix); 9 | } -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/shiny_cap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/goldenverba/server/frontend/out/shiny_cap.png -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/silver_cap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/goldenverba/server/frontend/out/silver_cap.png -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/verba.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/goldenverba/server/frontend/out/verba.glb -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/verba.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/goldenverba/server/frontend/out/verba.png -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/weaviate.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/goldenverba/server/frontend/out/weaviate.glb -------------------------------------------------------------------------------- /goldenverba/server/frontend/out/weaviate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/goldenverba/server/frontend/out/weaviate.png -------------------------------------------------------------------------------- /goldenverba/server/helpers.py: -------------------------------------------------------------------------------- 1 | from fastapi import WebSocket 2 | from goldenverba.server.types import ( 3 | FileStatus, 4 | StatusReport, 5 | DataBatchPayload, 6 | FileConfig, 7 | CreateNewDocument, 8 | ) 9 | from wasabi import msg 10 | 11 | 12 | class LoggerManager: 13 | def __init__(self, socket: WebSocket = None): 14 | self.socket = socket 15 | 16 | async def send_report( 17 | self, file_Id: str, status: FileStatus, message: str, took: float 18 | ): 19 | msg.info(f"{status} | {file_Id} | {message} | {took}") 20 | if self.socket is not None: 21 | payload: StatusReport = { 22 | "fileID": file_Id, 23 | "status": status, 24 | "message": message, 25 | "took": took, 26 | } 27 | 28 | await self.socket.send_json(payload) 29 | 30 | async def create_new_document( 31 | self, new_file_id: str, document_name: str, original_file_id: str 32 | ): 33 | msg.info(f"Creating new file {new_file_id} from {original_file_id}") 34 | if self.socket is not None: 35 | payload: CreateNewDocument = { 36 | "new_file_id": new_file_id, 37 | "filename": document_name, 38 | "original_file_id": original_file_id, 39 | } 40 | 41 | await self.socket.send_json(payload) 42 | 43 | 44 | class BatchManager: 45 | def __init__(self): 46 | self.batches = {} 47 | 48 | def add_batch(self, payload: DataBatchPayload) -> FileConfig: 49 | try: 50 | # msg.info(f"Receiving Batch for {payload.fileID} : {payload.order} of {payload.total}") 51 | 52 | if payload.fileID not in self.batches: 53 | self.batches[payload.fileID] = { 54 | "fileID": payload.fileID, 55 | "total": payload.total, 56 | "chunks": {}, 57 | } 58 | 59 | self.batches[payload.fileID]["chunks"][payload.order] = payload.chunk 60 | 61 | fileConfig = self.check_batch(payload.fileID) 62 | 63 | if fileConfig is not None or payload.isLastChunk: 64 | msg.info(f"Removing {payload.fileID} from BatchManager") 65 | del self.batches[payload.fileID] 66 | 67 | return fileConfig 68 | 69 | except Exception as e: 70 | msg.fail(f"Failed to add batch to BatchManager: {str(e)}") 71 | 72 | def check_batch(self, fileID: str): 73 | if len(self.batches[fileID]["chunks"].keys()) == self.batches[fileID]["total"]: 74 | msg.good(f"Collected all Batches of {fileID}") 75 | chunks = self.batches[fileID]["chunks"] 76 | data = "".join([chunks[chunk] for chunk in chunks]) 77 | return FileConfig.model_validate_json(data) 78 | else: 79 | return None 80 | -------------------------------------------------------------------------------- /goldenverba/tests/document/test_document.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from goldenverba.components.document import Document, create_document 3 | from goldenverba.server.types import FileConfig 4 | 5 | 6 | def test_document_initialization(): 7 | """Test basic document initialization""" 8 | doc = Document( 9 | title="Test Doc", 10 | content="This is a test document.", 11 | extension=".txt", 12 | fileSize=23, 13 | labels=["test"], 14 | source="local", 15 | meta={"key": "value"}, 16 | metadata="test metadata", 17 | ) 18 | 19 | assert doc.title == "Test Doc" 20 | assert doc.content == "This is a test document." 21 | assert doc.extension == ".txt" 22 | assert doc.fileSize == 23 23 | assert doc.labels == ["test"] 24 | assert doc.source == "local" 25 | assert doc.meta == {"key": "value"} 26 | assert doc.metadata == "test metadata" 27 | assert hasattr(doc, "spacy_doc") 28 | 29 | 30 | def test_document_json_serialization(): 31 | """Test document to/from JSON conversion""" 32 | original_doc = Document( 33 | title="Test Doc", 34 | content="Test content", 35 | extension=".txt", 36 | fileSize=12, 37 | labels=["test"], 38 | source="local", 39 | meta={"key": "value"}, 40 | metadata="test metadata", 41 | ) 42 | 43 | # Convert to JSON 44 | json_dict = Document.to_json(original_doc) 45 | 46 | # Convert back from JSON 47 | restored_doc = Document.from_json(json_dict, None) 48 | 49 | assert restored_doc.title == original_doc.title 50 | assert restored_doc.content == original_doc.content 51 | assert restored_doc.extension == original_doc.extension 52 | assert restored_doc.fileSize == original_doc.fileSize 53 | assert restored_doc.labels == original_doc.labels 54 | assert restored_doc.source == original_doc.source 55 | assert restored_doc.metadata == original_doc.metadata 56 | 57 | 58 | def test_create_document_from_file_config(): 59 | """Test document creation from FileConfig""" 60 | # TODO: Add test 61 | assert True 62 | 63 | 64 | def test_document_with_large_content(): 65 | """Test document initialization with content larger than batch size""" 66 | large_content = "Test sentence. " * 50000 # Creates a large string 67 | doc = Document(content=large_content) 68 | 69 | assert len(doc.content) > 500000 # Verify content is larger than MAX_BATCH_SIZE 70 | assert hasattr(doc, "spacy_doc") 71 | 72 | 73 | def test_invalid_json_document(): 74 | """Test document creation from invalid JSON""" 75 | invalid_dict = {"title": "Test"} # Missing required fields 76 | 77 | doc = Document.from_json(invalid_dict, None) 78 | assert doc is None 79 | 80 | 81 | def test_special_characters_in_content(): 82 | """Test document initialization with special characters in content""" 83 | content = ( 84 | "This is a test document with special characters: !@#$%^&*()_+-=[]{}|;:,.<>?~ " 85 | ) 86 | content += "Hej detta är ett test, jag bor på en ö" 87 | doc = Document(content=content) 88 | assert doc.content == content 89 | assert doc.spacy_doc.text == content 90 | assert doc.spacy_doc.sents is not None 91 | 92 | 93 | def test_arabic_in_content(): 94 | """Test document initialization with Arabic in content""" 95 | content = "نص اختبار باللغة العربية" 96 | doc = Document(content=content) 97 | assert doc.content == content 98 | assert doc.spacy_doc.text == content 99 | assert doc.spacy_doc.sents is not None 100 | -------------------------------------------------------------------------------- /img/api_screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/img/api_screen.png -------------------------------------------------------------------------------- /img/ollama_running.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/img/ollama_running.png -------------------------------------------------------------------------------- /img/thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/img/thumbnail.png -------------------------------------------------------------------------------- /img/verba.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/img/verba.gif -------------------------------------------------------------------------------- /img/verba_architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/img/verba_architecture.png -------------------------------------------------------------------------------- /img/verba_data.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/img/verba_data.png -------------------------------------------------------------------------------- /img/verba_deployment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/img/verba_deployment.png -------------------------------------------------------------------------------- /img/verba_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/img/verba_icon.png -------------------------------------------------------------------------------- /img/verba_rag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/img/verba_rag.png -------------------------------------------------------------------------------- /img/verba_screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/img/verba_screen.png -------------------------------------------------------------------------------- /img/verba_select_embedder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/img/verba_select_embedder.png -------------------------------------------------------------------------------- /img/verba_status.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weaviate/Verba/5db085cc1a65b2841d6372e82783d59bad36285b/img/verba_status.png -------------------------------------------------------------------------------- /pypi_commands.sh: -------------------------------------------------------------------------------- 1 | python setup.py sdist bdist_wheel 2 | 3 | twine upload dist/* -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import find_packages, setup 2 | 3 | setup( 4 | name="goldenverba", 5 | version="2.1.3", 6 | packages=find_packages(), 7 | python_requires=">=3.10.0,<3.13.0", 8 | entry_points={ 9 | "console_scripts": [ 10 | "verba=goldenverba.server.cli:cli", 11 | ], 12 | }, 13 | author="Weaviate", 14 | author_email="edward@weaviate.io", 15 | description="Welcome to Verba: The Golden RAGtriever, an open-source initiative designed to offer a streamlined, user-friendly interface for Retrieval-Augmented Generation (RAG) applications. In just a few easy steps, dive into your data and make meaningful interactions!", 16 | long_description=open("README.md", encoding="utf-8").read(), 17 | long_description_content_type="text/markdown", 18 | url="https://github.com/weaviate/Verba", 19 | classifiers=[ 20 | "License :: OSI Approved :: BSD License", 21 | "Programming Language :: Python :: 3.10", 22 | "Programming Language :: Python :: 3.11", 23 | "Programming Language :: Python :: 3.12", 24 | ], 25 | include_package_data=True, 26 | install_requires=[ 27 | "weaviate-client==4.9.6", 28 | "python-dotenv==1.0.0", 29 | "wasabi==1.1.2", 30 | "fastapi==0.111.1", 31 | "uvicorn[standard]==0.29.0", 32 | "gunicorn==22.0.0", 33 | "click==8.1.7", 34 | "asyncio==3.4.3", 35 | "tiktoken==0.6.0", 36 | "requests==2.31.0", 37 | "pypdf==4.3.1", 38 | "python-docx==1.1.2", 39 | "scikit-learn==1.5.1", 40 | "langchain-text-splitters==0.2.2", 41 | "spacy==3.7.5", 42 | "aiohttp==3.9.5", 43 | "markdownify==0.13.1", 44 | "aiofiles==24.1.0", 45 | "assemblyai==0.33.0", 46 | "beautifulsoup4==4.12.3", 47 | "langdetect==1.0.9", 48 | ], 49 | extras_require={ 50 | "dev": ["pytest", "wheel", "twine", "black>=23.7.0", "setuptools"], 51 | "google": [ 52 | "vertexai==1.46.0", 53 | ], 54 | "huggingface": [ 55 | "sentence-transformers==3.0.1", 56 | ], 57 | }, 58 | ) 59 | --------------------------------------------------------------------------------