[docs]definline_image(self,image_item:str)->str:# pass through if it's a url or base64 encodedifimage_item.startswith("http")orimage_item.startswith("data"):returnimage_item# otherwise, it's a local file - need to base64 encode itelse:image_path=self.path/image_itemwithopen(image_path,"rb")asf:base64_image=base64.b64encode(f.read()).decode("utf-8")ifimage_path.suffix==".png":returnf"data:image/png;base64,{base64_image}"elifimage_path.suffix==".jpg":returnf"data:image/jpeg;base64,{base64_image}"elifimage_path.suffix==".jpeg":returnf"data:image/jpeg;base64,{base64_image}"else:raiseValueError(f"Invalid image format {image_path.suffix} - currently only .png ""and .jpg / .jpeg are supported.")
[docs]defparse_content(self,content:str)->Union[str,List]:"""for parsing inline images"""# regular expression to parse markdown imagesimage=r"(?P<alt>!\[[^\]]*\])\((?P<filename>.*?)(?=\"|\))\)"matches=re.findall(image,content,flags=re.MULTILINE)iflen(matches)>0:content_items=[]content_chunks=re.split(image,content,flags=re.MULTILINE)current_chunk=0foriinrange(len(content_chunks)):# image entryif(current_chunk<len(matches)andcontent_chunks[i]==matches[current_chunk][0]):content_items.append({"type":"image_url","image_url":{"url":self.inline_image(matches[current_chunk][1].split(" ")[0].strip())},})# second part of image entryelif(current_chunk<len(matches)andcontent_chunks[i]==matches[current_chunk][1]):current_chunk+=1# text entryelse:iflen(content_chunks[i].strip())>0:content_items.append({"type":"text","text":content_chunks[i].strip()})returncontent_itemselse:returncontent
[docs]definvoke(self,data:BaseModel)->BaseModel:assertisinstance(data,SimpleModel)messages=[]separator=r"(?i)^\s*#?\s*("+"|".join(self.roles)+r")\s*:\s*\n"# get valid chunks - remove empty itemschunks=[itemforiteminre.split(separator,data.item,flags=re.MULTILINE)iflen(item.strip())>0]# if no starter role, then inject system roleifchunks[0].strip().lower()notinself.roles:chunks.insert(0,"system")# if last chunk is role entry, then remove (no content?)ifchunks[-1].strip().lower()inself.roles:chunks.pop()iflen(chunks)%2!=0:raiseValueError("Invalid prompt format")# create messagesforiinrange(0,len(chunks),2):role=chunks[i].strip().lower()content=chunks[i+1].strip()messages.append({"role":role,"content":self.parse_content(content)})returnSimpleModel[list](item=messages)