Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
File size: 6,386 Bytes
6e20157 f3d91b8 6e20157 f3d91b8 6e20157 f3d91b8 6e20157 f3d91b8 6e20157 f3d91b8 6e20157 f3d91b8 6e20157 f3d91b8 6e20157 f3d91b8 6e20157 f3d91b8 6e20157 f3d91b8 6e20157 f3d91b8 6e20157 f3d91b8 0182942 f3d91b8 6e20157 f3d91b8 6e20157 f3d91b8 6e20157 7d26f92 6e20157 f3d91b8 0182942 f3d91b8 6e20157 7d26f92 f3d91b8 6e20157 f3d91b8 6e20157 f3d91b8 6e20157 a1e1ca4 f3d91b8 6e20157 f3d91b8 400265e f3d91b8 6e20157 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
import os
import random
from functools import cache
from operator import itemgetter
import langsmith
from langchain.memory import ConversationBufferWindowMemory
from langchain.retrievers import EnsembleRetriever
from langchain_community.document_transformers import LongContextReorder
from langchain_core.documents import Document
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnableLambda
from langchain_openai.chat_models import ChatOpenAI
from .prompt_template import generate_prompt_template
from .retrievers_setup import (
DenseRetrieverClient,
SparseRetrieverClient,
compression_retriever_setup,
multi_query_retriever_setup,
)
# Helpers
def reorder_documents(docs: list[Document]) -> list[Document]:
"""Reorder documents to mitigate performance degradation with long contexts."""
return LongContextReorder().transform_documents(docs)
def randomize_documents(documents: list[Document]) -> list[Document]:
"""Randomize documents to vary model recommendations."""
random.shuffle(documents)
return documents
class DocumentFormatter:
def __init__(self, prefix: str):
self.prefix = prefix
def __call__(self, docs: list[Document]) -> str:
"""Format the Documents to markdown.
Args:
docs (list[Documents]): List of Langchain documents
Returns:
docs (str):
"""
return f"\n---\n".join(
[
f"- {self.prefix} {i+1}:\n\n\t" + d.page_content
for i, d in enumerate(docs)
]
)
def create_langsmith_client():
"""Create a Langsmith client."""
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_PROJECT"] = "talltree-ai-assistant"
os.environ["LANGCHAIN_ENDPOINT"] = "https://api.smith.langchain.com"
langsmith_api_key = os.getenv("LANGCHAIN_API_KEY")
if not langsmith_api_key:
raise EnvironmentError("Missing environment variable: LANGCHAIN_API_KEY")
return langsmith.Client()
# Set up Runnable and Memory
@cache
def get_rag_chain(
model_name: str = "gpt-4", temperature: float = 0.2
) -> tuple[ChatOpenAI, ConversationBufferWindowMemory]:
"""Set up runnable and chat memory
Args:
model_name (str, optional): LLM model. Defaults to "gpt-4" 30012024.
temperature (float, optional): Model temperature. Defaults to 0.2.
Returns:
Runnable, Memory: Chain and Memory
"""
RETRIEVER_PARAMETERS = {
"embeddings_model": "text-embedding-3-small",
"k_dense_practitioners_db": 8,
"k_sparse_practitioners_db": 15,
"weights_ensemble_practitioners_db": [0.2, 0.8],
"k_compression_practitioners_db": 18,
"k_dense_talltree": 6,
"k_compression_talltree": 6,
}
# Set up Langsmith to trace the chain
langsmith_tracing = create_langsmith_client()
# LLM and prompt template
llm = ChatOpenAI(
model_name=model_name,
temperature=temperature,
)
prompt = generate_prompt_template()
# Set retrievers pointing to the practitioners's dataset
dense_retriever_client = DenseRetrieverClient(
embeddings_model=RETRIEVER_PARAMETERS["embeddings_model"],
collection_name="practitioners_db",
search_type="similarity",
k=RETRIEVER_PARAMETERS["k_dense_practitioners_db"],
) # k x 4 using multiquery retriever
# Qdrant db as a retriever
practitioners_db_dense_retriever = dense_retriever_client.get_dense_retriever()
# Multiquery retriever using the dense retriever
# This retriever can be passed or not to the EnsembleRetriever. It uses GPT-3.5-turbo.
practitioners_db_dense_multiquery_retriever = multi_query_retriever_setup(
practitioners_db_dense_retriever
)
# Sparse vector retriever
sparse_retriever_client = SparseRetrieverClient(
collection_name="practitioners_db_sparse_collection",
vector_name="sparse_vector",
splade_model_id="naver/splade-cocondenser-ensembledistil",
k=RETRIEVER_PARAMETERS["k_sparse_practitioners_db"],
)
practitioners_db_sparse_retriever = sparse_retriever_client.get_sparse_retriever()
# Ensemble retriever for hyprid search (dense retriever seems to work better but the dense retriever is good for acronyms like RMT)
practitioners_ensemble_retriever = EnsembleRetriever(
retrievers=[
practitioners_db_dense_retriever,
practitioners_db_sparse_retriever,
],
weights=RETRIEVER_PARAMETERS["weights_ensemble_practitioners_db"],
)
# Compression retriever for practitioners db
practitioners_db_compression_retriever = compression_retriever_setup(
practitioners_ensemble_retriever,
embeddings_model=RETRIEVER_PARAMETERS["embeddings_model"],
k=RETRIEVER_PARAMETERS["k_compression_practitioners_db"],
)
# Set retrievers pointing to the tall_tree_db
dense_retriever_client = DenseRetrieverClient(
embeddings_model=RETRIEVER_PARAMETERS["embeddings_model"],
collection_name="tall_tree_db",
search_type="similarity",
k=RETRIEVER_PARAMETERS["k_dense_talltree"],
)
tall_tree_db_dense_retriever = dense_retriever_client.get_dense_retriever()
# Compression retriever for tall_tree_db
tall_tree_db_compression_retriever = compression_retriever_setup(
tall_tree_db_dense_retriever,
embeddings_model=RETRIEVER_PARAMETERS["embeddings_model"],
k=RETRIEVER_PARAMETERS["k_compression_talltree"],
)
# Set conversation history window memory. It only uses the last k interactions.
memory = ConversationBufferWindowMemory(
memory_key="history",
return_messages=True,
k=6,
)
# Set up runnable using LCEL
setup_and_retrieval = {
"practitioners_db": itemgetter("message")
| practitioners_db_compression_retriever
| DocumentFormatter("Practitioner #"),
"tall_tree_db": itemgetter("message")
| tall_tree_db_dense_retriever
| DocumentFormatter("No."),
"history": RunnableLambda(memory.load_memory_variables) | itemgetter("history"),
"message": itemgetter("message"),
}
chain = setup_and_retrieval | prompt | llm | StrOutputParser()
return chain, memory
|