Legal Semantic Search is a Next.js app that loads PDF files from its codebase into a Pinecone index and runs semantic search over them. The sample data is a set of legal cases, but you can apply the same code to any documents stored locally.
Built with
- Pinecone Database
- Voyage AI embeddings
- LangChain
- Next.js and Tailwind CSS
- Node.js 20 or later
Run the sample app
To create the app from the template, use thecreate-pinecone-app CLI:Terminal
Get your Pinecone API key
You need an API key to make calls to your Pinecone project:Then copy your generated key:You can also create a key in the Pinecone console. For more information, see Create an API key.
.env
Get your Voyage AI API key
- Create a Voyage AI account.
- Create an API key.
- Add your billing information. Voyage AI requires it even for the free tier.
- Copy your API key.
Create a Pinecone index
Create a serverless index that stores dense vectors, with the following settings:
- Dimension:
1024, which matches the Voyage AIvoyage-law-2embedding model. - Metric:
cosine - Region:
us-east-1
Install dependencies
The app requires Node.js 20 or later. From the project root directory, install the dependencies:
Terminal
Project structure
The app uses a standard Next.js project structure:- Frontend: Next.js, Tailwind CSS, and custom React components for the search experience. The frontend calls API routes that bootstrap the Pinecone index and fetch relevant document chunks for the UI.
- Backend: Next.js API routes that chunk files, upsert them to Pinecone, and return search results.
How it works
The app uses a basic semantic search architecture for low-latency natural language search across all embedded documents. When the app loads, it checks in the background whether the Pinecone index needs to be created and populated.Suggested searches
The search interface is a component that takes a list of suggested searches and shows them in a dropdown. To adapt the app to your own use case, define your own suggested searches in the parent component and pass them toSearchForm:TypeScript
SearchForm component is exported from src/components/SearchForm.tsx. It handles the following:- Displaying suggested searches.
- Letting the user search or clear the input.
- Showing the user that a search is in progress.
Local document processing
The codebase includes several landmark legal cases as PDFs, so when you run the app locally, you get the same experience as the hosted demo. The app uses LangChain to parse the PDFs, split them into chunks, and embed them. It stores the resulting vectors in a Pinecone index.Knowledge base bootstrapping
The following function bootstraps the Pinecone index from the PDF files in the codebase:TypeScript
- Creates the Pinecone index named in the
PINECONE_INDEXenvironment variable. - Loads metadata from the
docs/db.jsonfile. - Loads all PDFs in the
docsdirectory. - Merges the extracted metadata with the documents based on filename.
- Splits the text into chunks.
- Assigns a unique ID to each chunk and flattens its metadata.
- Upserts the chunks to the Pinecone index in batches.
Domain-specific embedding model
The app uses Voyage AI’svoyage-law-2 embedding model, which is built for legal text. The sample data is a small set of landmark U.S. cases from Justia.During bootstrapping, the app chunks the case documents and sends them to the Voyage AI model for embedding:TypeScript
/api/search route, which uses the same Voyage AI model to embed the query and then runs the search against the index:TypeScript