Added fix

This commit is contained in:
Vasilije 2023-08-23 16:25:15 +02:00
parent 39140620f6
commit 020570f57f
4 changed files with 424 additions and 175 deletions

View file

@ -168,12 +168,12 @@ def memory_factory(memory_type):
# pages = loader.load_and_split()
logging.info(" PDF split into pages")
Memory_ = Memory(user_id='555')
Memory_ = Memory(user_id=decoded_payload['user_id'])
await Memory_.async_init()
memory_class = getattr(Memory_, f"_add_{memory_type}_memory", None)
output= await memory_class(observation=str(loader))
output= await memory_class(observation=str(loader), params =decoded_payload['params'])
return JSONResponse(content={"response": output}, status_code=200)
except Exception as e:
@ -181,7 +181,7 @@ def memory_factory(memory_type):
return JSONResponse(content={"response": {"error": str(e)}}, status_code=503)
@app.post("/{memory_type}/fetch-memory", response_model=dict)
async def add_memory(
async def fetch_memory(
payload: Payload,
# files: List[UploadFile] = File(...),
):
@ -189,7 +189,7 @@ def memory_factory(memory_type):
decoded_payload = payload.payload
Memory_ = Memory(user_id='555')
Memory_ = Memory(user_id=decoded_payload['user_id'])
await Memory_.async_init()
@ -202,7 +202,7 @@ def memory_factory(memory_type):
return JSONResponse(content={"response": {"error": str(e)}}, status_code=503)
@app.post("/{memory_type}/delete-memory", response_model=dict)
async def add_memory(
async def delete_memory(
payload: Payload,
# files: List[UploadFile] = File(...),
):
@ -210,7 +210,7 @@ def memory_factory(memory_type):
decoded_payload = payload.payload
Memory_ = Memory(user_id='555')
Memory_ = Memory(user_id=decoded_payload['user_id'])
await Memory_.async_init()
@ -227,6 +227,29 @@ for memory_type in memory_list:
memory_factory(memory_type)
@app.get("/available-buffer-actions", response_model=dict)
async def available_buffer_actions(
payload: Payload,
# files: List[UploadFile] = File(...),
):
try:
decoded_payload = payload.payload
Memory_ = Memory(user_id=decoded_payload['user_id'])
await Memory_.async_init()
# memory_class = getattr(Memory_, f"_delete_{memory_type}_memory", None)
output = Memory_._available_operations()
return JSONResponse(content={"response": output}, status_code=200)
except Exception as e:
return JSONResponse(content={"response": {"error": str(e)}}, status_code=503)
#
# # Process each uploaded PDF file
# results = []

View file

@ -55,7 +55,7 @@ from langchain.schema import Document, SystemMessage, HumanMessage
from langchain.vectorstores import Weaviate
import weaviate
import uuid
import humanize
load_dotenv()
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY", "")
@ -542,7 +542,7 @@ class EpisodicBuffer:
vector_db = VectorDB(user_id=self.user_id, memory_id=self.memory_id, st_memory_id=self.st_memory_id,
index_name=self.index_name, db_type=self.db_type, namespace=namespace)
query = await vector_db.fetch_memories(observation=observation)
query = await vector_db.fetch_memories(observation=observation, namespace=namespace)
return query
async def _add_memories(self, observation: str, namespace: str, params: dict = None):
@ -555,175 +555,380 @@ class EpisodicBuffer:
async def _delete_memories(self, params: str = None) -> Coroutine[Any, Any, Any]:
"""Fetch related characteristics, preferences or dislikes for a user."""
# self.init_pinecone(index_name=self.index)
vector_db = VectorDB(user_id=self.user_id, memory_id=self.memory_id, st_memory_id=self.st_memory_id,
index_name=self.index_name, db_type=self.db_type, namespace=self.namespace)
if self.db_type == "weaviate":
return await self.vector_db.delete_memories(params=params)
return await vector_db.delete_memories(params=params)
elif self.db_type == "pinecone":
pass
# async def freshness(self, observation: str,namespace:str) -> str:
# """Freshness - Score between 1 and 5 on how often was the information processed in episodic memory in the past"""
#
# memory = Memory(user_id=self.user_id)
# await memory.async_init()
#
# # gg = await memory._run_buffer(user_input= "bla", content = "blablabla ")
# # print(gg)
#
#
#
# ggur = await memory._fetch_episodic_memory(observation=observation)
# print(ggur)
async def freshness(self, observation: str,namespace:str=None) -> list[str]:
"""Freshness - Score between 1 and 5 on how often was the information updated in episodic or semantic memory in the past"""
memory = Memory(user_id=self.user_id)
await memory.async_init()
lookup_value = await memory._fetch_episodic_memory(observation = observation)
unix_t = lookup_value["data"]["Get"]["EPISODICMEMORY"][0]["_additional"]["lastUpdateTimeUnix"]
# Convert Unix timestamp to datetime
last_update_datetime = datetime.fromtimestamp(int(unix_t) / 1000)
time_difference = datetime.now() - last_update_datetime
time_difference_text = humanize.naturaltime(time_difference)
marvin.settings.openai.api_key = os.environ.get('OPENAI_API_KEY')
@ai_classifier
class MemoryRoute(Enum):
"""Represents classifer for freshness of memories"""
data_uploaded_now = "0"
data_uploaded_very_recently = "1"
data_uploaded_recently = "2"
data_uploaded_more_than_a_month_ago = "3"
data_uploaded_more_than_three_months_ago = "4"
data_uploaded_more_than_six_months_ago = "5"
namespace = MemoryRoute(str(time_difference_text))
return [namespace.value, lookup_value]
async def frequency(self, observation: str,namespace:str) -> list[str]:
"""Frequency - Score between 1 and 5 on how often was the information processed in episodic memory in the past
Counts the number of times a memory was accessed in the past and divides it by the total number of memories in the episodic memory """
client = self.init_weaviate_client(self.namespace)
memory = Memory(user_id=self.user_id)
await memory.async_init()
result_output = await memory._fetch_episodic_memory(observation=observation)
number_of_relevant_events = len(result_output["data"]["Get"]["EPISODICMEMORY"])
number_of_total_events = client.query.aggregate( self.namespace).with_meta_count().do()
frequency = float(number_of_relevant_events) / float(number_of_total_events)
return [str(frequency), result_output["data"]["Get"]["EPISODICMEMORY"][0]]
async def relevance(self, observation: str) -> list[str]:
"""Relevance - Score between 1 and 5 on how often was the final information relevant to the user in the past.
Stored in the episodic memory, mainly to show how well a buffer did the job
Starts at 1, gets updated based on the user feedback """
return ["5", "memory"]
async def saliency(self, observation: str) -> list[str]:
"""Determines saliency by finding relevance between user input and document schema values.
After finding document schena value relevant for the user, it forms a new query based on the schema value and the user input """
return ["5", "memory"]
# @ai_classifier
# class MemoryRoute(Enum):
# """Represents classifer for semantic fetching of memories"""
# """Represents classifer for freshness of memories"""
#
# storage_of_documents_and_knowledge_to_memory = "SEMANTICMEMORY"
# raw_information_currently_processed_in_short_term_memory = "EPISODICBUFFER"
# raw_information_kept_in_short_term_memory = "SHORTTERMMEMORY"
# long_term_recollections_of_past_events_and_emotions = "EPISODICMEMORY"
# raw_information_to_store_as_events = "EVENTBUFFER"
# data_uploaded_now = "0"
# data_uploaded_very_recently = "1"
# data_uploaded_recently = "2"
# data_uploaded_more_than_a_month_ago = "3"
# data_uploaded_more_than_three_months_ago = "4"
# data_uploaded_more_than_six_months_ago = "5"
#
# namespace= MemoryRoute(observation)
# return ggur
async def encoding(self, document: str, namespace: str = "EPISODICBUFFER") -> None:
async def encoding(self, document: str, namespace: str = "EPISODICBUFFER", params:dict=None) -> list[str]:
"""Encoding for the buffer, stores raw data in the buffer
Note, this is not comp-sci encoding, but rather encoding in the sense of storing the content in the buffer"""
vector_db = VectorDB(user_id=self.user_id, memory_id=self.memory_id, st_memory_id=self.st_memory_id,
index_name=self.index_name, db_type=self.db_type, namespace=namespace)
query = await vector_db.add_memories(document)
query = await vector_db.add_memories(document, params=params)
return query
async def main_buffer(self, user_input=None, content=None):
"""AI buffer to convert unstructured data to structured data"""
# Here we define the user prompt and the structure of the output we desire
# prompt = output[0].page_content
async def available_operations(self) -> list[str]:
"""Determines what operations are available for the user to process PDFs"""
return ["translate", "structure", "load to database", "load to semantic memory", "load to episodic memory", "load to buffer"]
async def main_buffer(self, user_input=None, content=None, params=None):
"""AI buffer to understand user PDF query, prioritize memory info and process it based on available operations"""
list_of_operations = await self.available_operations()
#we just filter the data here
prompt_filter = ChatPromptTemplate.from_template(
"Filter and remove uneccessary information that is not relevant in the user query {query}")
chain_filter = prompt_filter | self.llm
output = await chain_filter.ainvoke({"query": user_input})
if params:
context =[]
if "freshness" in params:
params.get('freshness', None) # get the value of freshness
freshness = await self.freshness(observation=str(output))
context.append(freshness)
elif "frequency" in params:
params.get('freshness', None)
frequency = await self.freshness(observation=str(output))
print("freshness", frequency)
context.append(frequency)
#fix this so it actually filters
else:
#defaults to semantic search
memory = Memory(user_id=self.user_id)
await memory.async_init()
lookup_value_episodic = await memory._fetch_episodic_memory(observation=str(output))
lookup_value_semantic = await memory._fetch_episodic_memory(observation=str(output))
lookup_value_buffer = await self._fetch_memories(observation=str(output), namespace=self.namespace)
context = [lookup_value_episodic, lookup_value_semantic, lookup_value_buffer]
#copy the context over into the buffer
#do i need to do it for the episodic + raw data, might make sense
print("HERE WE ARE")
class Task(BaseModel):
"""Schema for an individual task."""
task_order: str = Field(..., description="The order at which the task needs to be performed")
task_name: str = Field(None, description="The task that needs to be performed")
operation: str = Field(None, description="The operation to be performed")
class TaskList(BaseModel):
"""Schema for the record containing a list of tasks."""
tasks: List[Task] = Field(..., description="List of tasks")
prompt_filter_chunk = f" Based on available operations {list_of_operations} determine only the relevant list of steps and operations sequentially based {output}"
# chain_filter_chunk = prompt_filter_chunk | self.llm.bind(function_call={"TaskList": "tasks"}, functions=TaskList)
# output_chunk = await chain_filter_chunk.ainvoke({"query": output, "list_of_operations": list_of_operations})
prompt_msgs = [
SystemMessage(
content="You are a world class algorithm for decomposing prompts into steps and operations and choosing relevant ones"
),
HumanMessage(content="Decompose based on the following prompt:"),
HumanMessagePromptTemplate.from_template("{input}"),
HumanMessage(content="Tips: Make sure to answer in the correct format"),
HumanMessage(content="Tips: Only choose actions that are relevant to the user query and ignore others")
]
prompt_ = ChatPromptTemplate(messages=prompt_msgs)
chain = create_structured_output_chain(TaskList, self.llm, prompt_, verbose=True)
from langchain.callbacks import get_openai_callback
with get_openai_callback() as cb:
output = await chain.arun(input=prompt_filter_chunk, verbose=True)
print(cb)
# output = json.dumps(output)
my_object = parse_obj_as(TaskList, output)
print("HERE IS THE OUTPUT", my_object.json())
data = json.loads(my_object.json())
# Extract the list of tasks
tasks_list = data["tasks"]
for task in tasks_list:
class TranslateText(BaseModel):
observation: str = Field(
description="observation we want to translate"
)
@tool("translate_to_en", args_schema=TranslateText, return_direct=True)
def translate_to_en(observation, args_schema=TranslateText):
"""Translate to English"""
out = GoogleTranslator(source='auto', target='en').translate(text=observation)
return out
agent = initialize_agent(
llm=self.llm,
tools=[translate_to_en],
agent=AgentType.OPENAI_FUNCTIONS,
verbose=True,
)
print("HERE IS THE TASK", task)
output = agent.run(input=task)
print(output)
await self.encoding(output)
buffer_result = await self._fetch_memories(observation=str(output), namespace=self.namespace)
#json here
prompt_filter = ChatPromptTemplate.from_template(
"Format and collect all outputs from the tasks presented here {tasks} and their results {results}")
chain_filter_chunk = prompt_filter | self.llm.bind(function_call={"TaskList": "tasks"}, functions=TaskList)
output = await chain_filter_chunk.ainvoke({"query": buffer_result})
print("HERE IS THE OUTPUT", output)
memory = Memory(user_id=self.user_id)
await memory.async_init()
lookup_value = await memory._add_episodic_memory(observation=str(output), params={})
#load to buffer once is done
#fetch everything in the current session and load to episodic memory
#for files where user input is provided and they are directly proccessed
#
# based on the semantic search , raw memory data will be fetched. also, episodic memory will be fetched
# they will be written down as a "context" for the user
# i get scores for the episodic memory and the semantic memory
# i get only the data with the highest score
# i use that data to form the context
# file_upload
#
if content is not None:
# operations -> translate, structure, load to db
#for files where user input is provided and they are directly proccessed
list_of_operations = ["translate", "structure", "load to db"]
prompt_filter = ChatPromptTemplate.from_template(
"Filter and remove uneccessary information that is not relevant in the user query {query}")
chain_filter = prompt_filter | self.llm
output = await chain_filter.ainvoke({"query": user_input})
class Task(BaseModel):
"""Schema for an individual task."""
task_order: str = Field(..., description="The order at which the task needs to be performed")
task_name: str = Field(None, description="The task that needs to be performed")
operation: str = Field(None, description="The operation to be performed")
class TaskList(BaseModel):
"""Schema for the record containing a list of tasks."""
tasks: List[Task] = Field(..., description="List of tasks")
prompt_filter_chunk = f" Based on available operations {list_of_operations} determine only the relevant list of steps and operations sequentially based {output}"
# chain_filter_chunk = prompt_filter_chunk | self.llm.bind(function_call={"TaskList": "tasks"}, functions=TaskList)
# output_chunk = await chain_filter_chunk.ainvoke({"query": output, "list_of_operations": list_of_operations})
prompt_msgs = [
SystemMessage(
content="You are a world class algorithm for decomposing prompts into steps and operations and choosing relevant ones"
),
HumanMessage(content="Decompose based on the following prompt:"),
HumanMessagePromptTemplate.from_template("{input}"),
HumanMessage(content="Tips: Make sure to answer in the correct format"),
HumanMessage(content="Tips: Only choose actions that are relevant to the user query and ignore others")
]
prompt_ = ChatPromptTemplate(messages=prompt_msgs)
chain = create_structured_output_chain(TaskList, self.llm, prompt_, verbose=True)
from langchain.callbacks import get_openai_callback
with get_openai_callback() as cb:
output = await chain.arun(input=prompt_filter_chunk, verbose=True)
print(cb)
# output = json.dumps(output)
my_object = parse_obj_as(TaskList, output)
print("HERE IS THE OUTPUT", my_object.json())
data = json.loads(my_object.json())
# Extract the list of tasks
tasks_list = data["tasks"]
for task in tasks_list:
class TranslateText(BaseModel):
observation: str = Field(
description="observation we want to translate"
)
@tool("translate_to_en", args_schema=TranslateText, return_direct=True)
def translate_to_en(observation, args_schema=TranslateText):
"""Translate to English"""
out = GoogleTranslator(source='auto', target='en').translate(text=observation)
return out
agent = initialize_agent(
llm=self.llm,
tools=[translate_to_en],
agent=AgentType.OPENAI_FUNCTIONS,
verbose=True,
)
agent.run(task)
# We need to encode the content. Note, this is not comp-sci encoding, but rather encoding in the sense of storing the content in the buffer
# output_translated = GoogleTranslator(source='auto', target='en').translate(text=content)
# await self.encoding(output_translated)
# freshness_score =await self.freshness(output_translated, namespace="EPISODICBUFFER")
# print(freshness_score)
# shows how much the data is relevant for the user, provided by the user in a separate step, starts at 0
user_relevance_score = "0"
# similarity score between the user input and the content already available in the buffer
# write this to episodic memory
# prompt_filter = ChatPromptTemplate.from_template("Filter and remove uneccessary information that is not relevant in the user query {query}")
# chain_filter = prompt_filter | self.llm
# output = await chain_filter.ainvoke({"query": user_input})
# print(output)
if content is None:
# Sensory and Linguistic Processing
prompt_filter = ChatPromptTemplate.from_template(
"Filter and remove uneccessary information that is not relevant in the user query {query}")
chain_filter = prompt_filter | self.llm
output = await chain_filter.ainvoke({"query": user_input})
translation = GoogleTranslator(source='auto', target='en').translate(text=output.content)
def top_down_processing():
"""Top-down processing"""
pass
def bottom_up_processing():
"""Bottom-up processing"""
pass
def interactive_processing():
"""interactive processing"""
pass
working_memory_activation = "bla"
prompt_chunk = ChatPromptTemplate.from_template(
"Can you break down the instruction 'Structure a PDF and load it into duckdb' into smaller tasks or actions? Return only tasks or actions. Be brief")
chain_chunk = prompt_chunk | self.llm
output_chunks = await chain_chunk.ainvoke({"query": output.content})
print(output_chunks.content)
#
# #
#
# if content is not None:
#
# # operations -> translate, structure, load to db
#
# list_of_operations = ["translate", "structure", "load to db"]
#
# prompt_filter = ChatPromptTemplate.from_template(
# "Filter and remove uneccessary information that is not relevant in the user query {query}")
# chain_filter = prompt_filter | self.llm
# output = await chain_filter.ainvoke({"query": user_input})
#
# class Task(BaseModel):
# """Schema for an individual task."""
# task_order: str = Field(..., description="The order at which the task needs to be performed")
# task_name: str = Field(None, description="The task that needs to be performed")
# operation: str = Field(None, description="The operation to be performed")
#
# class TaskList(BaseModel):
# """Schema for the record containing a list of tasks."""
# tasks: List[Task] = Field(..., description="List of tasks")
#
# prompt_filter_chunk = f" Based on available operations {list_of_operations} determine only the relevant list of steps and operations sequentially based {output}"
# # chain_filter_chunk = prompt_filter_chunk | self.llm.bind(function_call={"TaskList": "tasks"}, functions=TaskList)
# # output_chunk = await chain_filter_chunk.ainvoke({"query": output, "list_of_operations": list_of_operations})
# prompt_msgs = [
# SystemMessage(
# content="You are a world class algorithm for decomposing prompts into steps and operations and choosing relevant ones"
# ),
# HumanMessage(content="Decompose based on the following prompt:"),
# HumanMessagePromptTemplate.from_template("{input}"),
# HumanMessage(content="Tips: Make sure to answer in the correct format"),
# HumanMessage(content="Tips: Only choose actions that are relevant to the user query and ignore others")
#
# ]
# prompt_ = ChatPromptTemplate(messages=prompt_msgs)
# chain = create_structured_output_chain(TaskList, self.llm, prompt_, verbose=True)
# from langchain.callbacks import get_openai_callback
# with get_openai_callback() as cb:
# output = await chain.arun(input=prompt_filter_chunk, verbose=True)
# print(cb)
# # output = json.dumps(output)
# my_object = parse_obj_as(TaskList, output)
# print("HERE IS THE OUTPUT", my_object.json())
#
# data = json.loads(my_object.json())
#
# # Extract the list of tasks
# tasks_list = data["tasks"]
#
# for task in tasks_list:
# class TranslateText(BaseModel):
# observation: str = Field(
# description="observation we want to translate"
# )
#
# @tool("translate_to_en", args_schema=TranslateText, return_direct=True)
# def translate_to_en(observation, args_schema=TranslateText):
# """Translate to English"""
# out = GoogleTranslator(source='auto', target='en').translate(text=observation)
# return out
#
# agent = initialize_agent(
# llm=self.llm,
# tools=[translate_to_en],
# agent=AgentType.OPENAI_FUNCTIONS,
#
# verbose=True,
# )
#
# agent.run(task)
#
# # We need to encode the content. Note, this is not comp-sci encoding, but rather encoding in the sense of storing the content in the buffer
# # output_translated = GoogleTranslator(source='auto', target='en').translate(text=content)
# # await self.encoding(output_translated)
# # freshness_score =await self.freshness(output_translated, namespace="EPISODICBUFFER")
# # print(freshness_score)
# # shows how much the data is relevant for the user, provided by the user in a separate step, starts at 0
# user_relevance_score = "0"
# # similarity score between the user input and the content already available in the buffer
#
# # write this to episodic memory
#
# # prompt_filter = ChatPromptTemplate.from_template("Filter and remove uneccessary information that is not relevant in the user query {query}")
# # chain_filter = prompt_filter | self.llm
# # output = await chain_filter.ainvoke({"query": user_input})
#
# # print(output)
#
# if content is None:
# # Sensory and Linguistic Processing
# prompt_filter = ChatPromptTemplate.from_template(
# "Filter and remove uneccessary information that is not relevant in the user query {query}")
# chain_filter = prompt_filter | self.llm
# output = await chain_filter.ainvoke({"query": user_input})
# translation = GoogleTranslator(source='auto', target='en').translate(text=output.content)
#
# def top_down_processing():
# """Top-down processing"""
# pass
#
# def bottom_up_processing():
# """Bottom-up processing"""
# pass
#
# def interactive_processing():
# """interactive processing"""
# pass
#
# working_memory_activation = "bla"
#
# prompt_chunk = ChatPromptTemplate.from_template(
# "Can you break down the instruction 'Structure a PDF and load it into duckdb' into smaller tasks or actions? Return only tasks or actions. Be brief")
# chain_chunk = prompt_chunk | self.llm
# output_chunks = await chain_chunk.ainvoke({"query": output.content})
#
# print(output_chunks.content)
# vectorstore = Weaviate.from_documents(documents, embeddings, client=client, by_text=False)
# retriever = WeaviateHybridSearchRetriever(
@ -969,10 +1174,11 @@ class Memory:
return await self.short_term_memory.episodic_buffer._fetch_memories(observation=user_input, namespace=namespace)
async def _delete_buffer_memory(self, params: str = None):
return await self.long_term_memory.episodic_buffer._delete_memories(
return await self.short_term_memory.episodic_buffer._delete_memories(
params=params
)
async def _available_operations(self):
return await self.long_term_memory.episodic_buffer._available_operations()
async def main():
memory = Memory(user_id="123")
@ -994,15 +1200,34 @@ async def main():
gg = await memory._run_buffer(user_input="i NEED TRANSLATION TO GERMAN ", content="i NEED TRANSLATION TO GERMAN ")
print(gg)
# gg = await memory._delete_episodic_memory()
# gg = await memory._delete_buffer_memory()
# print(gg)
# ggur = await memory._add_episodic_memory(observation = "bla bla bla", params=params)
episodic = """{
"start_date": "2023-08-23",
"end_date": "2023-08-30",
"user_query": "How can I plan a healthy diet?",
"action_steps": [
{
"step_number": 1,
"description": "Research and gather information about basic principles of a healthy diet."
},
{
"step_number": 2,
"description": "Create a weekly meal plan that includes a variety of nutritious foods."
},
{
"step_number": 3,
"description": "Prepare and cook meals according to your meal plan. Include fruits, vegetables, lean proteins, and whole grains."
}
]
}"""
#
# ggur = await memory._add_episodic_memory(observation = episodic, params=params)
# print(ggur)
# ggur = await memory._fetch_episodic_memory(observation = "bla bla bla")
# print(ggur)
# fff = await memory._fetch_memories_buffer(user_input = "bla bla bla", namespace="Test")
# print(fff)
# fff = await memory._fetch_episodic_memory(observation = "healthy diet")
# print(len(fff["data"]["Get"]["EPISODICMEMORY"]))
if __name__ == "__main__":

40
level_2/poetry.lock generated
View file

@ -261,17 +261,17 @@ numpy = {version = ">=1.19.0", markers = "python_version >= \"3.9\""}
[[package]]
name = "boto3"
version = "1.28.30"
version = "1.28.32"
description = "The AWS SDK for Python"
optional = false
python-versions = ">= 3.7"
files = [
{file = "boto3-1.28.30-py3-none-any.whl", hash = "sha256:e095ede98d3680e65966ab71f273b7d86938f5d853773ef96f4cb646277c2a4b"},
{file = "boto3-1.28.30.tar.gz", hash = "sha256:2b509a959966a572f15db5768a18066ce1f53022ac53fca9421c620219fa3998"},
{file = "boto3-1.28.32-py3-none-any.whl", hash = "sha256:ed787f250ce2562c7744395bdf32b5a7bc9184126ef50a75e97bcb66043dccf3"},
{file = "boto3-1.28.32.tar.gz", hash = "sha256:b505faa126db84e226f6f8d242a798fae30a725f0cac8a76c6aca9ace4e8eb28"},
]
[package.dependencies]
botocore = ">=1.31.30,<1.32.0"
botocore = ">=1.31.32,<1.32.0"
jmespath = ">=0.7.1,<2.0.0"
s3transfer = ">=0.6.0,<0.7.0"
@ -280,13 +280,13 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"]
[[package]]
name = "botocore"
version = "1.31.30"
version = "1.31.32"
description = "Low-level, data-driven core of boto 3."
optional = false
python-versions = ">= 3.7"
files = [
{file = "botocore-1.31.30-py3-none-any.whl", hash = "sha256:269f20dcadd8dfd0c26d0e6fbceb84814ff6638ff3aafcc5324b9fb9949a7051"},
{file = "botocore-1.31.30.tar.gz", hash = "sha256:3cf6a9d7621b897c9ff23cd02113826141b3dd3d7e90273b661efc4dc05f84e2"},
{file = "botocore-1.31.32-py3-none-any.whl", hash = "sha256:8992ac186988c4b4cc168e8e479e9472da1442b193c1bf7c9dcd1877ec62d23c"},
{file = "botocore-1.31.32.tar.gz", hash = "sha256:7a07d8dc8cc47bf23af39409ada81f388eb78233e1bb2cde0c415756da753664"},
]
[package.dependencies]
@ -1053,13 +1053,13 @@ requests = ">=2.20.0,<3.0"
[[package]]
name = "gptcache"
version = "0.1.39.1"
version = "0.1.40"
description = "GPTCache, a powerful caching library that can be used to speed up and lower the cost of chat applications that rely on the LLM service. GPTCache works as a memcache for AIGC applications, similar to how Redis works for traditional applications."
optional = false
python-versions = ">=3.8.1"
files = [
{file = "gptcache-0.1.39.1-py3-none-any.whl", hash = "sha256:81355f7878e12a820dccb017f8a45ea44b73178dac07108c56db664a476a4a07"},
{file = "gptcache-0.1.39.1.tar.gz", hash = "sha256:a9c629fdeaa94b78a6cfe707a5f9a3a52b361655a3f01327709ca00c78a500eb"},
{file = "gptcache-0.1.40-py3-none-any.whl", hash = "sha256:ba323e5e46b100fa7663b5f4d164cc2aee60f343184ed03ec2d2bb95e9f47c50"},
{file = "gptcache-0.1.40.tar.gz", hash = "sha256:5fe4bcf3a45946177cb845b3e1ec01159f10622600e1384b9de0c7c6065d10d5"},
]
[package.dependencies]
@ -1415,13 +1415,13 @@ data = ["language-data (>=1.1,<2.0)"]
[[package]]
name = "langsmith"
version = "0.0.25"
version = "0.0.26"
description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform."
optional = false
python-versions = ">=3.8.1,<4.0"
files = [
{file = "langsmith-0.0.25-py3-none-any.whl", hash = "sha256:d595435ad21fa6077550d7c85472935d1e8241afa042c1e29287d2c95c3ed151"},
{file = "langsmith-0.0.25.tar.gz", hash = "sha256:e728c398fc1adaa0ed8abeb21f6a92d7fb19fe3ab49d3911c22b03dfe25935d6"},
{file = "langsmith-0.0.26-py3-none-any.whl", hash = "sha256:61c1d4582104d96edde04e1eea1dae347645b691c44489a5871341a2a1a2a1eb"},
{file = "langsmith-0.0.26.tar.gz", hash = "sha256:80a4ef1b663a24a460d25b9986ab2010c5d06b6061c65be473abafc0647d191a"},
]
[package.dependencies]
@ -3561,13 +3561,13 @@ colorama = {version = ">=0.4.6", markers = "sys_platform == \"win32\" and python
[[package]]
name = "weaviate-client"
version = "3.22.1"
version = "3.23.0"
description = "A python native Weaviate client"
optional = false
python-versions = ">=3.8"
files = [
{file = "weaviate-client-3.22.1.tar.gz", hash = "sha256:aff61bd3f5d74df20a62328443e3aa9c860d5330fdfb19c4d8ddc44cb604032f"},
{file = "weaviate_client-3.22.1-py3-none-any.whl", hash = "sha256:01843a4899a227300e570409e77628e9d1b28476313f94943c37aee3f75112e1"},
{file = "weaviate-client-3.23.0.tar.gz", hash = "sha256:3ffd7f1460c9e32755d84d4f5fc63dfc0bd990dbe2c3dc20d5c68119d467680e"},
{file = "weaviate_client-3.23.0-py3-none-any.whl", hash = "sha256:3d3bb75c1d96b2b71e213c5eb885ae3e3f42e4304955383c467d100187d9ff8e"},
]
[package.dependencies]
@ -3581,13 +3581,13 @@ grpc = ["grpcio", "grpcio-tools"]
[[package]]
name = "wheel"
version = "0.41.1"
version = "0.41.2"
description = "A built-package format for Python"
optional = false
python-versions = ">=3.7"
files = [
{file = "wheel-0.41.1-py3-none-any.whl", hash = "sha256:473219bd4cbedc62cea0cb309089b593e47c15c4a2531015f94e4e3b9a0f6981"},
{file = "wheel-0.41.1.tar.gz", hash = "sha256:12b911f083e876e10c595779709f8a88a59f45aacc646492a67fe9ef796c1b47"},
{file = "wheel-0.41.2-py3-none-any.whl", hash = "sha256:75909db2664838d015e3d9139004ee16711748a52c8f336b52882266540215d8"},
{file = "wheel-0.41.2.tar.gz", hash = "sha256:0c5ac5ff2afb79ac23ab82bab027a0be7b5dbcf2e54dc50efe4bf507de1f7985"},
]
[package.extras]
@ -3795,4 +3795,4 @@ multidict = ">=4.0"
[metadata]
lock-version = "2.0"
python-versions = "^3.10"
content-hash = "13258c777467d93ab73021225322da670e42513cedec6252a40aacf74822ea68"
content-hash = "788ca51ba313eac5f1dbcadfd7f91109b8b7a7734a1f16e10c8fb2e3b435a606"

View file

@ -39,6 +39,7 @@ dlt = { version ="^0.3.8", extras = ["duckdb"]}
weaviate-client = "^3.22.1"
python-multipart = "^0.0.6"
deep-translator = "^1.11.4"
humanize = "^4.8.0"