mirror of
https://github.com/hwchase17/langchain.git
synced 2025-05-28 10:39:23 +00:00
LLMRails (#10796)
### LLMRails Integration This PR provides integration with LLMRails. Implemented here are: langchain/vectorstore/llm_rails.py tests/integration_tests/vectorstores/test_llm_rails.py docs/extras/integrations/vectorstores/llm-rails.ipynb --------- Co-authored-by: Anar Aliyev <aaliyev@mgmt.cloudnet.services> Co-authored-by: Bagatur <baskaryan@gmail.com>
This commit is contained in:
parent
900dbd1cbe
commit
c656a6b966
328
docs/extras/integrations/vectorstores/llm_rails.ipynb
Normal file
328
docs/extras/integrations/vectorstores/llm_rails.ipynb
Normal file
@ -0,0 +1,328 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "683953b3",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# LLMRails\n",
|
||||
"\n",
|
||||
">[LLMRails](https://www.llmrails.com/) is a API platform for building GenAI applications. It provides an easy-to-use API for document indexing and querying that is managed by LLMRails and is optimized for performance and accuracy. \n",
|
||||
"See the [LLMRails API documentation ](https://docs.llmrails.com/) for more information on how to use the API.\n",
|
||||
"\n",
|
||||
"This notebook shows how to use functionality related to the `LLMRails`'s integration with langchain.\n",
|
||||
"Note that unlike many other integrations in this category, LLMRails provides an end-to-end managed service for retrieval agumented generation, which includes:\n",
|
||||
"1. A way to extract text from document files and chunk them into sentences.\n",
|
||||
"2. Its own embeddings model and vector store - each text segment is encoded into a vector embedding and stored in the LLMRails internal vector store\n",
|
||||
"3. A query service that automatically encodes the query into embedding, and retrieves the most relevant text segments (including support for [Hybrid Search](https://docs.llmrails.com/datastores/search))\n",
|
||||
"\n",
|
||||
"All of these are supported in this LangChain integration."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "dc0f4344",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Setup\n",
|
||||
"\n",
|
||||
"You will need a LLMRails account to use LLMRails with LangChain. To get started, use the following steps:\n",
|
||||
"1. [Sign up](https://console.llmrails.com/signup) for a LLMRails account if you don't already have one.\n",
|
||||
"2. Next you'll need to create API keys to access the API. Click on the **\"API Keys\"** tab in the corpus view and then the **\"Create API Key\"** button. Give your key a name. Click \"Create key\" and you now have an active API key. Keep this key confidential. \n",
|
||||
"\n",
|
||||
"To use LangChain with LLMRails, you'll need to have this value: api_key.\n",
|
||||
"You can provide those to LangChain in two ways:\n",
|
||||
"\n",
|
||||
"1. Include in your environment these two variables: `LLM_RAILS_API_KEY`, `LLM_RAILS_DATASTORE_ID`.\n",
|
||||
"\n",
|
||||
"> For example, you can set these variables using os.environ and getpass as follows:\n",
|
||||
"\n",
|
||||
"```python\n",
|
||||
"import os\n",
|
||||
"import getpass\n",
|
||||
"\n",
|
||||
"os.environ[\"LLM_RAILS_API_KEY\"] = getpass.getpass(\"LLMRails API Key:\")\n",
|
||||
"os.environ[\"LLM_RAILS_DATASTORE_ID\"] = getpass.getpass(\"LLMRails Datastore Id:\")\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"1. Provide them as arguments when creating the LLMRails vectorstore object:\n",
|
||||
"\n",
|
||||
"```python\n",
|
||||
"vectorstore = LLMRails(\n",
|
||||
" api_key=llm_rails_api_key,\n",
|
||||
" datastore_id=datastore_id\n",
|
||||
")\n",
|
||||
"```"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "d93c4fcd",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Adding text\n",
|
||||
"\n",
|
||||
"For adding text to your datastore first you have to go to [Datastores](https://console.llmrails.com/datastores) page and create one. Click Create Datastore button and choose a name and embedding model for your datastore. Then get your datastore id from newly created datatore settings.\n",
|
||||
" "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"id": "920f4644",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from langchain.vectorstores import LLMRails\n",
|
||||
"import os\n",
|
||||
"\n",
|
||||
"os.environ['LLM_RAILS_DATASTORE_ID'] = 'Your datastore id '\n",
|
||||
"os.environ['LLM_RAILS_API_KEY'] = 'Your API Key'\n",
|
||||
"\n",
|
||||
"llm_rails = LLMRails.from_texts(['Your text here'])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "1f9215c8",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2023-04-04T09:27:29.920258Z",
|
||||
"start_time": "2023-04-04T09:27:29.913714Z"
|
||||
}
|
||||
},
|
||||
"source": [
|
||||
"## Similarity search\n",
|
||||
"\n",
|
||||
"The simplest scenario for using LLMRails is to perform a similarity search. "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"id": "a8c513ab",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2023-04-04T10:51:25.204469Z",
|
||||
"start_time": "2023-04-04T10:51:24.855618Z"
|
||||
},
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"query = \"What do you plan to do about national security?\"\n",
|
||||
"found_docs = llm_rails.similarity_search(\n",
|
||||
" query, k=5\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"id": "fc516993",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2023-04-04T10:51:25.220984Z",
|
||||
"start_time": "2023-04-04T10:51:25.213943Z"
|
||||
},
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Others may not be democratic but nevertheless depend upon a rules-based international system.\n",
|
||||
"\n",
|
||||
"Yet what we share in common, and the prospect of a freer and more open world, makes such a broad coalition necessary and worthwhile.\n",
|
||||
"\n",
|
||||
"We will listen to and consider ideas that our partners suggest about how to do this.\n",
|
||||
"\n",
|
||||
"Building this inclusive coalition requires reinforcing the multilateral system to uphold the founding principles of the United Nations, including respect for international law.\n",
|
||||
"\n",
|
||||
"141 countries expressed support at the United Nations General Assembly for a resolution condemning Russia’s unprovoked aggression against Ukraine.\n",
|
||||
"\n",
|
||||
"We continue to demonstrate this approach by engaging all regions across all issues, not in terms of what we are against but what we are for.\n",
|
||||
"\n",
|
||||
"This year, we partnered with ASEAN to advance clean energy infrastructure and maritime security in the region.\n",
|
||||
"\n",
|
||||
"We kickstarted the Prosper Africa Build Together Campaign to fuel economic growth across the continent and bolster trade and investment in the clean energy, health, and digital technology sectors.\n",
|
||||
"\n",
|
||||
"We are working to develop a partnership with countries on the Atlantic Ocean to establish and carry out a shared approach to advancing our joint development, economic, environmental, scientific, and maritime governance goals.\n",
|
||||
"\n",
|
||||
"We galvanized regional action to address the core challenges facing the Western Hemisphere by spearheading the Americas Partnership for Economic Prosperity to drive economic recovery and by mobilizing the region behind a bold and unprecedented approach to migration through the Los Angeles Declaration on Migration and Protection.\n",
|
||||
"\n",
|
||||
"In the Middle East, we have worked to enhance deterrence toward Iran, de-escalate regional conflicts, deepen integration among a diverse set of partners in the region, and bolster energy stability.\n",
|
||||
"\n",
|
||||
"A prime example of an inclusive coalition is IPEF, which we launched alongside a dozen regional partners that represent 40 percent of the world’s GDP.\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"print(found_docs[0].page_content)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "1bda9bf5",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Similarity search with score\n",
|
||||
"\n",
|
||||
"Sometimes we might want to perform the search, but also obtain a relevancy score to know how good is a particular result."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"id": "8804a21d",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2023-04-04T10:51:25.631585Z",
|
||||
"start_time": "2023-04-04T10:51:25.227384Z"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"query = \"What is your approach to national defense\"\n",
|
||||
"found_docs = llm_rails.similarity_search_with_score(\n",
|
||||
" query, k=5,\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"id": "756a6887",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2023-04-04T10:51:25.642282Z",
|
||||
"start_time": "2023-04-04T10:51:25.635947Z"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"But we will do so as the last resort and only when the objectives and mission are clear and achievable, consistent with our values and laws, alongside non-military tools, and the mission is undertaken with the informed consent of the American people.\n",
|
||||
"\n",
|
||||
"Our approach to national defense is described in detail in the 2022 National Defense Strategy.\n",
|
||||
"\n",
|
||||
"Our starting premise is that a powerful U.S. military helps advance and safeguard vital U.S. national interests by backstopping diplomacy, confronting aggression, deterring conflict, projecting strength, and protecting the American people and their economic interests.\n",
|
||||
"\n",
|
||||
"Amid intensifying competition, the military’s role is to maintain and gain warfighting advantages while limiting those of our competitors.\n",
|
||||
"\n",
|
||||
"The military will act urgently to sustain and strengthen deterrence, with the PRC as its pacing challenge.\n",
|
||||
"\n",
|
||||
"We will make disciplined choices regarding our national defense and focus our attention on the military’s primary responsibilities: to defend the homeland, and deter attacks and aggression against the United States, our allies and partners, while being prepared to fight and win the Nation’s wars should diplomacy and deterrence fail.\n",
|
||||
"\n",
|
||||
"To do so, we will combine our strengths to achieve maximum effect in deterring acts of aggression—an approach we refer to as integrated deterrence (see text box on page 22).\n",
|
||||
"\n",
|
||||
"We will operate our military using a campaigning mindset—sequencing logically linked military activities to advance strategy-aligned priorities.\n",
|
||||
"\n",
|
||||
"And, we will build a resilient force and defense ecosystem to ensure we can perform these functions for decades to come.\n",
|
||||
"\n",
|
||||
"We ended America’s longest war in Afghanistan, and with it an era of major military operations to remake other societies, even as we have maintained the capacity to address terrorist threats to the American people as they emerge.\n",
|
||||
"\n",
|
||||
"20 NATIONAL SECURITY STRATEGY Page 21 \n",
|
||||
"\n",
|
||||
"A combat-credible military is the foundation of deterrence and America’s ability to prevail in conflict.\n",
|
||||
"\n",
|
||||
"Score: 0.5040982687179959\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"document, score = found_docs[0]\n",
|
||||
"print(document.page_content)\n",
|
||||
"print(f\"\\nScore: {score}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "691a82d6",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## LLMRails as a Retriever\n",
|
||||
"\n",
|
||||
"LLMRails, as all the other LangChain vectorstores, is most often used as a LangChain Retriever:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"id": "9427195f",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2023-04-04T10:51:26.031451Z",
|
||||
"start_time": "2023-04-04T10:51:26.018763Z"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"LLMRailsRetriever(tags=None, metadata=None, vectorstore=<langchain.vectorstores.llm_rails.LLMRails object at 0x107b9c040>, search_type='similarity', search_kwargs={'k': 5})"
|
||||
]
|
||||
},
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"retriever = llm_rails.as_retriever()\n",
|
||||
"retriever"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"id": "f3c70c31",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2023-04-04T10:51:26.495652Z",
|
||||
"start_time": "2023-04-04T10:51:26.046407Z"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"Document(page_content='But we will do so as the last resort and only when the objectives and mission are clear and achievable, consistent with our values and laws, alongside non-military tools, and the mission is undertaken with the informed consent of the American people.\\n\\nOur approach to national defense is described in detail in the 2022 National Defense Strategy.\\n\\nOur starting premise is that a powerful U.S. military helps advance and safeguard vital U.S. national interests by backstopping diplomacy, confronting aggression, deterring conflict, projecting strength, and protecting the American people and their economic interests.\\n\\nAmid intensifying competition, the military’s role is to maintain and gain warfighting advantages while limiting those of our competitors.\\n\\nThe military will act urgently to sustain and strengthen deterrence, with the PRC as its pacing challenge.\\n\\nWe will make disciplined choices regarding our national defense and focus our attention on the military’s primary responsibilities: to defend the homeland, and deter attacks and aggression against the United States, our allies and partners, while being prepared to fight and win the Nation’s wars should diplomacy and deterrence fail.\\n\\nTo do so, we will combine our strengths to achieve maximum effect in deterring acts of aggression—an approach we refer to as integrated deterrence (see text box on page 22).\\n\\nWe will operate our military using a campaigning mindset—sequencing logically linked military activities to advance strategy-aligned priorities.\\n\\nAnd, we will build a resilient force and defense ecosystem to ensure we can perform these functions for decades to come.\\n\\nWe ended America’s longest war in Afghanistan, and with it an era of major military operations to remake other societies, even as we have maintained the capacity to address terrorist threats to the American people as they emerge.\\n\\n20 NATIONAL SECURITY STRATEGY Page 21 \\x90\\x90\\x90\\x90\\x90\\x90\\n\\nA combat-credible military is the foundation of deterrence and America’s ability to prevail in conflict.', metadata={'type': 'file', 'url': 'https://cdn.llmrails.com/dst_d94b490c-4638-4247-ad5e-9aa0e7ef53c1/c2d63a2ea3cd406cb522f8312bc1535d', 'name': 'Biden-Harris-Administrations-National-Security-Strategy-10.2022.pdf'})"
|
||||
]
|
||||
},
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"query = \"What is your approach to national defense\"\n",
|
||||
"retriever.get_relevant_documents(query)[0]"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.10.4"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
@ -46,6 +46,7 @@ from langchain.vectorstores.epsilla import Epsilla
|
||||
from langchain.vectorstores.faiss import FAISS
|
||||
from langchain.vectorstores.hologres import Hologres
|
||||
from langchain.vectorstores.lancedb import LanceDB
|
||||
from langchain.vectorstores.llm_rails import LLMRails
|
||||
from langchain.vectorstores.marqo import Marqo
|
||||
from langchain.vectorstores.matching_engine import MatchingEngine
|
||||
from langchain.vectorstores.meilisearch import Meilisearch
|
||||
@ -107,6 +108,7 @@ __all__ = [
|
||||
"FAISS",
|
||||
"Hologres",
|
||||
"LanceDB",
|
||||
"LLMRails",
|
||||
"Marqo",
|
||||
"MatchingEngine",
|
||||
"Meilisearch",
|
||||
|
203
libs/langchain/langchain/vectorstores/llm_rails.py
Normal file
203
libs/langchain/langchain/vectorstores/llm_rails.py
Normal file
@ -0,0 +1,203 @@
|
||||
"""Wrapper around LLMRails vector database."""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import uuid
|
||||
from enum import Enum
|
||||
from typing import Any, Iterable, List, Optional, Tuple
|
||||
|
||||
import requests
|
||||
|
||||
from langchain.pydantic_v1 import Field
|
||||
from langchain.schema import Document
|
||||
from langchain.schema.embeddings import Embeddings
|
||||
from langchain.vectorstores.base import VectorStore, VectorStoreRetriever
|
||||
|
||||
|
||||
class ModelChoices(str, Enum):
|
||||
embedding_english_v1 = "embedding-english-v1"
|
||||
embedding_multi_v1 = "embedding-multi-v1"
|
||||
|
||||
|
||||
class LLMRails(VectorStore):
|
||||
"""Implementation of Vector Store using LLMRails (https://llmrails.com/).
|
||||
Example:
|
||||
.. code-block:: python
|
||||
|
||||
from langchain.vectorstores import LLMRails
|
||||
|
||||
vectorstore = LLMRails(
|
||||
api_key=llm_rails_api_key,
|
||||
datastore_id=datastore_id
|
||||
)
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
datastore_id: Optional[str] = None,
|
||||
api_key: Optional[str] = None,
|
||||
):
|
||||
"""Initialize with LLMRails API."""
|
||||
self._datastore_id = datastore_id or os.environ.get("LLM_RAILS_DATASTORE_ID")
|
||||
self._api_key = api_key or os.environ.get("LLM_RAILS_API_KEY")
|
||||
if self._api_key is None:
|
||||
logging.warning("Can't find Rails credentials in environment.")
|
||||
|
||||
self._session = requests.Session() # to reuse connections
|
||||
self.datastore_id = datastore_id
|
||||
self.base_url = "https://api.llmrails.com/v1"
|
||||
|
||||
def _get_post_headers(self) -> dict:
|
||||
"""Returns headers that should be attached to each post request."""
|
||||
return {
|
||||
"X-API-KEY": self._api_key,
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
|
||||
def add_texts(
|
||||
self,
|
||||
texts: Iterable[str],
|
||||
metadatas: Optional[List[dict]] = None,
|
||||
**kwargs: Any,
|
||||
) -> List[str]:
|
||||
"""Run more texts through the embeddings and add to the vectorstore.
|
||||
|
||||
Args:
|
||||
texts: Iterable of strings to add to the vectorstore.
|
||||
|
||||
Returns:
|
||||
List of ids from adding the texts into the vectorstore.
|
||||
|
||||
"""
|
||||
names: List[str] = []
|
||||
for text in texts:
|
||||
doc_name = str(uuid.uuid4())
|
||||
response = self._session.post(
|
||||
f"{self.base_url}/datastores/{self._datastore_id}/text",
|
||||
json={"name": doc_name, "text": text},
|
||||
verify=True,
|
||||
headers=self._get_post_headers(),
|
||||
)
|
||||
|
||||
if response.status_code != 200:
|
||||
logging.error(
|
||||
f"Create request failed for doc_name = {doc_name} with status code "
|
||||
f"{response.status_code}, reason {response.reason}, text "
|
||||
f"{response.text}"
|
||||
)
|
||||
|
||||
return names
|
||||
|
||||
names.append(doc_name)
|
||||
|
||||
return names
|
||||
|
||||
def similarity_search_with_score(
|
||||
self, query: str, k: int = 5
|
||||
) -> List[Tuple[Document, float]]:
|
||||
"""Return LLMRails documents most similar to query, along with scores.
|
||||
|
||||
Args:
|
||||
query: Text to look up documents similar to.
|
||||
k: Number of Documents to return. Defaults to 5 Max 10.
|
||||
alpha: parameter for hybrid search .
|
||||
|
||||
Returns:
|
||||
List of Documents most similar to the query and score for each.
|
||||
"""
|
||||
response = self._session.post(
|
||||
headers=self._get_post_headers(),
|
||||
url=f"{self.base_url}/datastores/{self._datastore_id}/search",
|
||||
data=json.dumps({"k": k, "text": query}),
|
||||
timeout=10,
|
||||
)
|
||||
|
||||
if response.status_code != 200:
|
||||
logging.error(
|
||||
"Query failed %s",
|
||||
f"(code {response.status_code}, reason {response.reason}, details "
|
||||
f"{response.text})",
|
||||
)
|
||||
return []
|
||||
|
||||
results = response.json()["results"]
|
||||
docs = [
|
||||
(
|
||||
Document(
|
||||
page_content=x["text"],
|
||||
metadata={
|
||||
key: value
|
||||
for key, value in x["metadata"].items()
|
||||
if key != "score"
|
||||
},
|
||||
),
|
||||
x["metadata"]["score"],
|
||||
)
|
||||
for x in results
|
||||
]
|
||||
|
||||
return docs
|
||||
|
||||
def similarity_search(
|
||||
self, query: str, k: int = 4, **kwargs: Any
|
||||
) -> List[Document]:
|
||||
"""Return LLMRails documents most similar to query, along with scores.
|
||||
|
||||
Args:
|
||||
query: Text to look up documents similar to.
|
||||
k: Number of Documents to return. Defaults to 5.
|
||||
|
||||
Returns:
|
||||
List of Documents most similar to the query
|
||||
"""
|
||||
docs_and_scores = self.similarity_search_with_score(query, k=k)
|
||||
|
||||
return [doc for doc, _ in docs_and_scores]
|
||||
|
||||
@classmethod
|
||||
def from_texts(
|
||||
cls,
|
||||
texts: List[str],
|
||||
embedding: Optional[Embeddings] = None,
|
||||
metadatas: Optional[List[dict]] = None,
|
||||
**kwargs: Any,
|
||||
) -> LLMRails:
|
||||
"""Construct LLMRails wrapper from raw documents.
|
||||
This is intended to be a quick way to get started.
|
||||
Example:
|
||||
.. code-block:: python
|
||||
|
||||
from langchain.vectorstores import LLMRails
|
||||
llm_rails = LLMRails.from_texts(
|
||||
texts,
|
||||
datastore_id=datastore_id,
|
||||
api_key=llm_rails_api_key
|
||||
)
|
||||
"""
|
||||
# Note: LLMRails generates its own embeddings, so we ignore the provided
|
||||
# embeddings (required by interface)
|
||||
llm_rails = cls(**kwargs)
|
||||
llm_rails.add_texts(texts)
|
||||
return llm_rails
|
||||
|
||||
def as_retriever(self, **kwargs: Any) -> LLMRailsRetriever:
|
||||
return LLMRailsRetriever(vectorstore=self, **kwargs)
|
||||
|
||||
|
||||
class LLMRailsRetriever(VectorStoreRetriever):
|
||||
vectorstore: LLMRails
|
||||
search_kwargs: dict = Field(default_factory=lambda: {"k": 5})
|
||||
"""Search params.
|
||||
k: Number of Documents to return. Defaults to 5.
|
||||
alpha: parameter for hybrid search .
|
||||
"""
|
||||
|
||||
def add_texts(self, texts: List[str]) -> None:
|
||||
"""Add text to the datastore.
|
||||
|
||||
Args:
|
||||
texts (List[str]): The text
|
||||
"""
|
||||
self.vectorstore.add_texts(texts)
|
@ -0,0 +1,35 @@
|
||||
from langchain.vectorstores.llm_rails import LLMRails
|
||||
|
||||
#
|
||||
# For this test to run properly, please setup as follows:
|
||||
# 1. Create a LLMRails account: sign up at https://console.llmrails.com/signup
|
||||
# 2. Create an API_KEY for this corpus with permissions for query and indexing
|
||||
# 3. Create a datastorea and get its id from datastore setting
|
||||
# 3. Setup environment variable:
|
||||
# LLM_RAILS_API_KEY, LLM_RAILS_DATASTORE_ID
|
||||
#
|
||||
|
||||
|
||||
def test_llm_rails_add_documents() -> None:
|
||||
"""Test end to end construction and search."""
|
||||
|
||||
# create a new Vectara instance
|
||||
docsearch: LLMRails = LLMRails()
|
||||
|
||||
# start with some initial texts, added with add_texts
|
||||
texts1 = ["large language model", "information retrieval", "question answering"]
|
||||
docsearch.add_texts(texts1)
|
||||
|
||||
# test without filter
|
||||
output1 = docsearch.similarity_search("large language model", k=1)
|
||||
|
||||
print(output1)
|
||||
assert len(output1) == 1
|
||||
assert output1[0].page_content == "large language model"
|
||||
|
||||
# test without filter but with similarity score
|
||||
output2 = docsearch.similarity_search_with_score("large language model", k=1)
|
||||
|
||||
assert len(output2) == 1
|
||||
assert output2[0][0].page_content == "large language model"
|
||||
assert output2[0][1] > 0
|
Loading…
Reference in New Issue
Block a user