Source code for langchain_aws.vectorstores.inmemorydb.filters
fromenumimportEnumfromfunctoolsimportwrapsfromtypingimportAny,Callable,Dict,List,Optional,Set,Tuple,Unionfromlangchain_aws.utilities.redisimportTokenEscaper# disable mypy error for dunder method overrides# mypy: disable-error-code="override"
[docs]classInMemoryDBFilterOperator(Enum):"""InMemoryDBFilterOperator enumerator is used to create InMemoryDBFilterExpressions"""EQ=1NE=2LT=3GT=4LE=5GE=6OR=7AND=8LIKE=9IN=10
[docs]classInMemoryDBFilter:"""Collection of InMemoryDBFilterFields."""
[docs]classInMemoryDBFilterField:"""Base class for InMemoryDBFilterFields."""escaper:"TokenEscaper"=TokenEscaper()OPERATORS:Dict[InMemoryDBFilterOperator,str]={}
def_set_value(self,val:Any,val_type:Tuple[Any],operator:InMemoryDBFilterOperator)->None:# check that the operator is supported by this classifoperatornotinself.OPERATORS:raiseValueError(f"Operator {operator} not supported by {self.__class__.__name__}. "+f"Supported operators are {self.OPERATORS.values()}.")ifnotisinstance(val,val_type):raiseTypeError(f"Right side argument passed to operator {self.OPERATORS[operator]} "f"with left side "f"argument {self.__class__.__name__} must be of type {val_type}, "f"received value {val}")self._value=valself._operator=operator
[docs]defcheck_operator_misuse(func:Callable)->Callable:"""Decorator to check for misuse of equality operators."""@wraps(func)defwrapper(instance:Any,*args:Any,**kwargs:Any)->Any:# Extracting 'other' from positional arguments or keyword argumentsother=kwargs.get("other")if"other"inkwargselseNoneifnotother:forarginargs:ifisinstance(arg,type(instance)):other=argbreakifisinstance(other,type(instance)):raiseValueError("Equality operators are overridden for FilterExpression creation. Use "".equals() for equality checks")returnfunc(instance,*args,**kwargs)returnwrapper
[docs]classInMemoryDBTag(InMemoryDBFilterField):"""InMemoryDBFilterField representing a tag in a InMemoryDB index."""OPERATORS:Dict[InMemoryDBFilterOperator,str]={InMemoryDBFilterOperator.EQ:"==",InMemoryDBFilterOperator.NE:"!=",InMemoryDBFilterOperator.IN:"==",}OPERATOR_MAP:Dict[InMemoryDBFilterOperator,str]={InMemoryDBFilterOperator.EQ:"@%s:{%s}",InMemoryDBFilterOperator.NE:"(-@%s:{%s})",InMemoryDBFilterOperator.IN:"@%s:{%s}",}SUPPORTED_VAL_TYPES=(list,set,tuple,str,type(None))
[docs]def__init__(self,field:str):"""Create a InMemoryDBTag FilterField. Args: field (str): The name of the InMemoryDBTag field in the index to be queried against. """super().__init__(field)
def_set_tag_value(self,other:Union[List[str],Set[str],Tuple[str],str],operator:InMemoryDBFilterOperator,)->None:ifisinstance(other,(list,set,tuple)):try:# "if val" clause removes non-truthy values from listother=[str(val)forvalinotherifval]exceptValueError:raiseValueError("All tags within collection must be strings")# above to catch the "" caseelifnotother:other=[]elifisinstance(other,str):other=[other]self._set_value(other,self.SUPPORTED_VAL_TYPES,operator)# type: ignore@check_operator_misusedef__eq__(self,other:Union[List[str],Set[str],Tuple[str],str])->"InMemoryDBFilterExpression":"""Create a InMemoryDBTag equality filter expression. Args: other (Union[List[str], Set[str], Tuple[str], str]): The tag(s) to filter on. Example: >>> from langchain_community.vectorstores.InMemoryDB import InMemoryDBTag >>> filter = InMemoryDBTag("brand") == "nike" """self._set_tag_value(other,InMemoryDBFilterOperator.EQ)returnInMemoryDBFilterExpression(str(self))@check_operator_misusedef__ne__(self,other:Union[List[str],Set[str],Tuple[str],str])->"InMemoryDBFilterExpression":"""Create a InMemoryDBTag inequality filter expression. Args: other (Union[List[str], Set[str], Tuple[str], str]): The tag(s) to filter on. Example: >>> from langchain_community.vectorstores.InMemoryDB import InMemoryDBTag >>> filter = InMemoryDBTag("brand") != "nike" """self._set_tag_value(other,InMemoryDBFilterOperator.NE)returnInMemoryDBFilterExpression(str(self))@propertydef_formatted_tag_value(self)->str:return"|".join([self.escaper.escape(tag)fortaginself._value])def__str__(self)->str:"""Return the query syntax for a InMemoryDBTag filter expression."""ifnotself._value:return"*"returnself.OPERATOR_MAP[self._operator]%(self._field,self._formatted_tag_value,)
[docs]classInMemoryDBNum(InMemoryDBFilterField):"""InMemoryDBFilterField representing a numeric field in a InMemoryDB index."""OPERATORS:Dict[InMemoryDBFilterOperator,str]={InMemoryDBFilterOperator.EQ:"==",InMemoryDBFilterOperator.NE:"!=",InMemoryDBFilterOperator.LT:"<",InMemoryDBFilterOperator.GT:">",InMemoryDBFilterOperator.LE:"<=",InMemoryDBFilterOperator.GE:">=",}OPERATOR_MAP:Dict[InMemoryDBFilterOperator,str]={InMemoryDBFilterOperator.EQ:"@%s:[%s%s]",InMemoryDBFilterOperator.NE:"(-@%s:[%s%s])",InMemoryDBFilterOperator.GT:"@%s:[(%s +inf]",InMemoryDBFilterOperator.LT:"@%s:[-inf (%s]",InMemoryDBFilterOperator.GE:"@%s:[%s +inf]",InMemoryDBFilterOperator.LE:"@%s:[-inf %s]",}SUPPORTED_VAL_TYPES=(int,float,type(None))def__str__(self)->str:"""Return the query syntax for a InMemoryDBNum filter expression."""ifself._valueisNone:return"*"if(self._operator==InMemoryDBFilterOperator.EQorself._operator==InMemoryDBFilterOperator.NE):returnself.OPERATOR_MAP[self._operator]%(self._field,self._value,self._value,)else:returnself.OPERATOR_MAP[self._operator]%(self._field,self._value)@check_operator_misusedef__eq__(self,other:Union[int,float])->"InMemoryDBFilterExpression":"""Create a Numeric equality filter expression. Args: other (Union[int, float]): The value to filter on. Example: >>> from langchain_community.vectorstores.InMemoryDB import InMemoryDBNum >>> filter = InMemoryDBNum("zipcode") == 90210 """self._set_value(other,self.SUPPORTED_VAL_TYPES,InMemoryDBFilterOperator.EQ)# type: ignorereturnInMemoryDBFilterExpression(str(self))@check_operator_misusedef__ne__(self,other:Union[int,float])->"InMemoryDBFilterExpression":"""Create a Numeric inequality filter expression. Args: other (Union[int, float]): The value to filter on. Example: >>> from langchain_community.vectorstores.InMemoryDB import InMemoryDBNum >>> filter = InMemoryDBNum("zipcode") != 90210 """self._set_value(other,self.SUPPORTED_VAL_TYPES,InMemoryDBFilterOperator.NE)# type: ignorereturnInMemoryDBFilterExpression(str(self))def__gt__(self,other:Union[int,float])->"InMemoryDBFilterExpression":"""Create a Numeric greater than filter expression. Args: other (Union[int, float]): The value to filter on. Example: >>> from langchain_community.vectorstores.InMemoryDB import InMemoryDBNum >>> filter = InMemoryDBNum("age") > 18 """self._set_value(other,self.SUPPORTED_VAL_TYPES,InMemoryDBFilterOperator.GT)# type: ignorereturnInMemoryDBFilterExpression(str(self))def__lt__(self,other:Union[int,float])->"InMemoryDBFilterExpression":"""Create a Numeric less than filter expression. Args: other (Union[int, float]): The value to filter on. Example: >>> from langchain_community.vectorstores.InMemoryDB import InMemoryDBNum >>> filter = InMemoryDBNum("age") < 18 """self._set_value(other,self.SUPPORTED_VAL_TYPES,InMemoryDBFilterOperator.LT)# type: ignorereturnInMemoryDBFilterExpression(str(self))def__ge__(self,other:Union[int,float])->"InMemoryDBFilterExpression":"""Create a Numeric greater than or equal to filter expression. Args: other (Union[int, float]): The value to filter on. Example: >>> from langchain_community.vectorstores.InMemoryDB import InMemoryDBNum >>> filter = InMemoryDBNum("age") >= 18 """self._set_value(other,self.SUPPORTED_VAL_TYPES,InMemoryDBFilterOperator.GE)# type: ignorereturnInMemoryDBFilterExpression(str(self))def__le__(self,other:Union[int,float])->"InMemoryDBFilterExpression":"""Create a Numeric less than or equal to filter expression. Args: other (Union[int, float]): The value to filter on. Example: >>> from langchain_community.vectorstores.InMemoryDB import InMemoryDBNum >>> filter = InMemoryDBNum("age") <= 18 """self._set_value(other,self.SUPPORTED_VAL_TYPES,InMemoryDBFilterOperator.LE)# type: ignorereturnInMemoryDBFilterExpression(str(self))
[docs]classInMemoryDBText(InMemoryDBFilterField):"""InMemoryDBFilterField representing a text field in a InMemoryDB index."""OPERATORS:Dict[InMemoryDBFilterOperator,str]={InMemoryDBFilterOperator.EQ:"==",InMemoryDBFilterOperator.NE:"!=",InMemoryDBFilterOperator.LIKE:"%",}OPERATOR_MAP:Dict[InMemoryDBFilterOperator,str]={InMemoryDBFilterOperator.EQ:'@%s:("%s")',InMemoryDBFilterOperator.NE:'(-@%s:"%s")',InMemoryDBFilterOperator.LIKE:"@%s:(%s)",}SUPPORTED_VAL_TYPES=(str,type(None))@check_operator_misusedef__eq__(self,other:str)->"InMemoryDBFilterExpression":"""Create a InMemoryDBText equality (exact match) filter expression. Args: other (str): The text value to filter on. Example: >>> from langchain_community.vectorstores.InMemoryDB import InMemoryDBText >>> filter = InMemoryDBText("job") == "engineer" """self._set_value(other,self.SUPPORTED_VAL_TYPES,InMemoryDBFilterOperator.EQ)# type: ignorereturnInMemoryDBFilterExpression(str(self))@check_operator_misusedef__ne__(self,other:str)->"InMemoryDBFilterExpression":"""Create a InMemoryDBText inequality filter expression. Args: other (str): The text value to filter on. Example: >>> from langchain_community.vectorstores.InMemoryDB import InMemoryDBText >>> filter = InMemoryDBText("job") != "engineer" """self._set_value(other,self.SUPPORTED_VAL_TYPES,InMemoryDBFilterOperator.NE)# type: ignorereturnInMemoryDBFilterExpression(str(self))def__mod__(self,other:str)->"InMemoryDBFilterExpression":"""Create a InMemoryDBText "LIKE" filter expression. Args: other (str): The text value to filter on. Example: >>> from langchain_aws.vectorstores.inmemorydb import InMemoryDBText >>> filter = InMemoryDBText("job") % "engine*" # suffix wild card match >>> filter = InMemoryDBText("job") % "%%engine%%" # fuzzy match w/ LD >>> filter = InMemoryDBText("job") % "engineer|doctor" # contains either >>> filter = InMemoryDBText("job") % "engineer doctor" # contains both """self._set_value(other,self.SUPPORTED_VAL_TYPES,InMemoryDBFilterOperator.LIKE)# type: ignorereturnInMemoryDBFilterExpression(str(self))def__str__(self)->str:"""Return the query syntax for a InMemoryDBText filter expression."""ifnotself._value:return"*"returnself.OPERATOR_MAP[self._operator]%(self._field,self._value,)
[docs]classInMemoryDBFilterExpression:"""Logical expression of InMemoryDBFilterFields. InMemoryDBFilterExpressions can be combined using the & and | operators to create complex logical expressions that evaluate to the InMemoryDB Query language. This presents an interface by which users can create complex queries without having to know the InMemoryDB Query language. Filter expressions are not initialized directly. Instead they are built by combining InMemoryDBFilterFields using the & and | operators. Examples: >>> from langchain_aws.vectorstores.inmemorydb import ( ... InMemoryDBTag, InMemoryDBNum ... ) >>> brand_is_nike = InMemoryDBTag("brand") == "nike" >>> price_is_under_100 = InMemoryDBNum("price") < 100 >>> filter = brand_is_nike & price_is_under_100 >>> print(str(filter)) (@brand:{nike} @price:[-inf (100)]) """
def__str__(self)->str:# top level check that allows recursive calls to __str__ifnotself._filterandnotself._operator:raiseValueError("Improperly initialized InMemoryDBFilterExpression")# if there's an operator, combine expressions accordinglyifself._operator:ifnotisinstance(self._left,InMemoryDBFilterExpression)ornotisinstance(self._right,InMemoryDBFilterExpression):raiseTypeError("Improper combination of filters.""Both left and right should be type FilterExpression")operator_str=(" | "ifself._operator==InMemoryDBFilterOperator.ORelse" ")returnself.format_expression(self._left,self._right,operator_str)# check that base case, the filter is setifnotself._filter:raiseValueError("Improperly initialized InMemoryDBFilterExpression")returnself._filter