Update utils.py
Browse files
utils.py
CHANGED
|
@@ -278,62 +278,94 @@ def document_storage_chroma(splits):
|
|
| 278 |
#HF embeddings--------------------------------------
|
| 279 |
#Chroma.from_documents(documents = splits, embedding = HuggingFaceEmbeddings(model_name="sentence-transformers/all-mpnet-base-v2", model_kwargs={"device": "cpu"}, encode_kwargs={'normalize_embeddings': False}), persist_directory = PATH_WORK + CHROMA_DIR)
|
| 280 |
return vectorstore, retriever
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 281 |
|
|
|
|
|
|
|
| 282 |
|
| 283 |
-
|
| 284 |
-
|
| 285 |
-
def document_storage_mongodb(splits):
|
| 286 |
-
MongoDBAtlasVectorSearch.from_documents(documents = splits,
|
| 287 |
-
embedding = OpenAIEmbeddings(disallowed_special = ()),
|
| 288 |
-
collection = MONGODB_COLLECTION,
|
| 289 |
-
index_name = MONGODB_INDEX_NAME)
|
| 290 |
-
############################################
|
| 291 |
-
#dokumente in chroma db vektorisiert ablegen können - die Db vorbereiten daüfur
|
| 292 |
-
def document_retrieval_chroma(llm, prompt):
|
| 293 |
-
#OpenAI embeddings -------------------------------
|
| 294 |
-
embeddings = OpenAIEmbeddings()
|
| 295 |
|
| 296 |
-
#
|
| 297 |
-
|
| 298 |
-
|
| 299 |
-
|
| 300 |
-
|
| 301 |
|
| 302 |
-
#
|
| 303 |
-
|
| 304 |
-
return db
|
| 305 |
|
| 306 |
-
|
| 307 |
-
|
| 308 |
-
|
| 309 |
-
|
| 310 |
-
|
| 311 |
-
|
| 312 |
-
|
| 313 |
-
|
| 314 |
-
|
| 315 |
-
#embeddings = HuggingFaceInstructEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2", model_kwargs={"device": "cpu"})
|
| 316 |
-
#etwas weniger rechenaufwendig:
|
| 317 |
-
#embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-mpnet-base-v2", model_kwargs={"device": "cpu"}, encode_kwargs={'normalize_embeddings': False})
|
| 318 |
-
#oder einfach ohne Langchain:
|
| 319 |
-
#embeddings = SentenceTransformerEmbeddings(model_name="all-MiniLM-L6-v2")
|
| 320 |
-
|
| 321 |
-
#ChromaDb um die embedings zu speichern
|
| 322 |
-
db = Chroma(embedding_function = embeddings, persist_directory = PATH_WORK + CHROMA_DIR)
|
| 323 |
-
print ("Chroma DB bereit ...................")
|
| 324 |
-
|
| 325 |
-
return db
|
| 326 |
-
|
| 327 |
-
###########################################
|
| 328 |
-
#dokumente in mongo db vektorisiert ablegen können - die Db vorbereiten daüfür
|
| 329 |
-
def document_retrieval_mongodb(llm, prompt):
|
| 330 |
-
db = MongoDBAtlasVectorSearch.from_connection_string(MONGODB_URI,
|
| 331 |
-
MONGODB_DB_NAME + "." + MONGODB_COLLECTION_NAME,
|
| 332 |
-
OpenAIEmbeddings(disallowed_special = ()),
|
| 333 |
-
index_name = MONGODB_INDEX_NAME)
|
| 334 |
-
return db
|
| 335 |
-
"""
|
| 336 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 337 |
|
| 338 |
|
| 339 |
###############################################
|
|
@@ -1120,7 +1152,7 @@ class GraphState(TypedDict):
|
|
| 1120 |
#Methoden, um den Graph und die Zustände umzusetzen
|
| 1121 |
### Nodes ###
|
| 1122 |
# die Knoten des Graphen definieren, die der Reihe noch (bzw. je nach Outcome des Vorgänger Knotens) durchlaufen werden
|
| 1123 |
-
def retrieve(state):
|
| 1124 |
"""
|
| 1125 |
Retrieve documents
|
| 1126 |
Args:
|
|
|
|
| 278 |
#HF embeddings--------------------------------------
|
| 279 |
#Chroma.from_documents(documents = splits, embedding = HuggingFaceEmbeddings(model_name="sentence-transformers/all-mpnet-base-v2", model_kwargs={"device": "cpu"}, encode_kwargs={'normalize_embeddings': False}), persist_directory = PATH_WORK + CHROMA_DIR)
|
| 280 |
return vectorstore, retriever
|
| 281 |
+
|
| 282 |
+
#Dokumente, die vom Retriever rausgesucht wurden auf Relevanz untersuchen
|
| 283 |
+
def grade_documents_direct(state):
|
| 284 |
+
print("---CHECK RELEVANCE---")
|
| 285 |
+
# Data model
|
| 286 |
+
class grade(BaseModel):
|
| 287 |
+
"""Binary score for relevance check."""
|
| 288 |
+
binary_score: str = Field(description="Relevanz Bewertung 'ja' oder 'nein'")
|
| 289 |
|
| 290 |
+
# LLM
|
| 291 |
+
model = ChatOpenAI(temperature=0.3, model="gpt-4-0125-preview", streaming=True)
|
| 292 |
|
| 293 |
+
# Tool
|
| 294 |
+
grade_tool_oai = convert_to_openai_tool(grade)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 295 |
|
| 296 |
+
# LLM with tool and enforce invocation
|
| 297 |
+
llm_with_tool = model.bind(
|
| 298 |
+
tools=[convert_to_openai_tool(grade_tool_oai)],
|
| 299 |
+
tool_choice={"type": "function", "function": {"name": "grade"}},
|
| 300 |
+
)
|
| 301 |
|
| 302 |
+
# Parser
|
| 303 |
+
parser_tool = PydanticToolsParser(tools=[grade])
|
|
|
|
| 304 |
|
| 305 |
+
# Prompt
|
| 306 |
+
prompt = PromptTemplate(
|
| 307 |
+
template="""Du bist ein Bewerter, der die Relevanz von einem erhaltenen Dokument zu einer Nutzeranfrage bewerten soll. \n
|
| 308 |
+
Hier ist das erhaltene Dokument: \n\n {context} \n\n
|
| 309 |
+
Hier ist die Nutzeranfrage: {question} \n
|
| 310 |
+
Wenn das erhaltene Dokument Keywörter oder semantische Bedeutung in Bezug auf die Nutzeranfrage hat, bewerte es als relevant. \n
|
| 311 |
+
Gib eine binäre Bewertung von 'ja' oder 'nein' Bewertung, um anzuzeigen ob das Dokuemnt relevant ist zur Nutzeranfrage oder nicht.""",
|
| 312 |
+
input_variables=["context", "question"],
|
| 313 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 314 |
|
| 315 |
+
# Chain
|
| 316 |
+
chain = prompt | llm_with_tool | parser_tool
|
| 317 |
+
|
| 318 |
+
# Score
|
| 319 |
+
filtered_docs = []
|
| 320 |
+
anzahl_relevant = 0
|
| 321 |
+
search = "nein" # Default do not opt for re-questioning to supplement retrieval
|
| 322 |
+
for d in documents:
|
| 323 |
+
score = chain.invoke({"question": question, "context": d.page_content})
|
| 324 |
+
grade = score[0].binary_score
|
| 325 |
+
if grade == "ja":
|
| 326 |
+
#search = "nein" # mind. ein relevantes Dokument -> keine Websuche nötig
|
| 327 |
+
print("---Bewertung: Dokument ist relevant---")
|
| 328 |
+
anzahl_relevant = anzahl_relevant +1
|
| 329 |
+
filtered_docs.append(d)
|
| 330 |
+
else:
|
| 331 |
+
print("---Bewertung: Dokument irrelevant---")
|
| 332 |
+
search = "ja" # mind ein Dokument irrelevant -> Frage umformulieren
|
| 333 |
+
continue
|
| 334 |
+
#wenn mehrheit der Dokumente relevant -> generieren starten damit
|
| 335 |
+
if (anzahl_relevant>= len(documents)/2):
|
| 336 |
+
search = "nein"
|
| 337 |
+
print("second trial grade_docs:.....................")
|
| 338 |
+
print(second_trial)
|
| 339 |
+
return filtered_docs
|
| 340 |
+
|
| 341 |
+
|
| 342 |
+
def transform_query_direct(query):
|
| 343 |
+
print("---TRANSFORM QUERY---")
|
| 344 |
+
state_dict = state["keys"]
|
| 345 |
+
question = state_dict["question"]
|
| 346 |
+
documents = state_dict["documents"]
|
| 347 |
+
|
| 348 |
+
# Create a prompt template with format instructions and the query
|
| 349 |
+
prompt = PromptTemplate(
|
| 350 |
+
template="""Du generierst Fragen, die optimiert sind für das Retrieval von Dokumenten. \n
|
| 351 |
+
Schaue auf den input und versuche die zugrundeliegende Absicht / Bedeutung zu bewerten. \n
|
| 352 |
+
Hier ist die ursprüngliche Frage:
|
| 353 |
+
\n ------- \n
|
| 354 |
+
{question}
|
| 355 |
+
\n ------- \n
|
| 356 |
+
Formuliere eine verbesserte Frage: """,
|
| 357 |
+
input_variables=["question"],
|
| 358 |
+
)
|
| 359 |
+
|
| 360 |
+
# Grader
|
| 361 |
+
model = ChatOpenAI(temperature=0, model="gpt-4-0125-preview", streaming=True)
|
| 362 |
+
|
| 363 |
+
# Prompt
|
| 364 |
+
chain = prompt | model | StrOutputParser()
|
| 365 |
+
better_question = chain.invoke({"question": question})
|
| 366 |
+
second_trial="ja"
|
| 367 |
+
|
| 368 |
+
return {"keys": {"documents": documents, "question": better_question, "second_trial" : second_trial}}
|
| 369 |
|
| 370 |
|
| 371 |
###############################################
|
|
|
|
| 1152 |
#Methoden, um den Graph und die Zustände umzusetzen
|
| 1153 |
### Nodes ###
|
| 1154 |
# die Knoten des Graphen definieren, die der Reihe noch (bzw. je nach Outcome des Vorgänger Knotens) durchlaufen werden
|
| 1155 |
+
def retrieve(state, retriever):
|
| 1156 |
"""
|
| 1157 |
Retrieve documents
|
| 1158 |
Args:
|