disable vector-base knowledge base.
This commit is contained in:
@@ -1,8 +0,0 @@
|
||||
name = "JarvisPlus"
|
||||
input.module = "scan_local"
|
||||
input.params.workspace = "${myai_dir}/workspace/JarvisPlus"
|
||||
input.params.path = "${myai_dir}/data"
|
||||
parser.module = "parse_local"
|
||||
parser.params.workspace = "${myai_dir}/workspace/JarvisPlus"
|
||||
parser.params.assign_to = "JarvisPlus"
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
import sys
|
||||
import os
|
||||
from aios import KnowledgePipelineEnvironment
|
||||
directory = os.path.dirname(__file__)
|
||||
sys.path.append(directory + '/../../../../src/component/')
|
||||
|
||||
from mail_environment import LocalEmail
|
||||
def init(env: KnowledgePipelineEnvironment, params: dict):
|
||||
return LocalEmail(env, params)
|
||||
@@ -1,10 +0,0 @@
|
||||
import sys
|
||||
import os
|
||||
from aios import *
|
||||
directory = os.path.dirname(__file__)
|
||||
|
||||
sys.path.append(directory + '/../../../../src/component/')
|
||||
from mail_environment import IssueParser
|
||||
|
||||
def init(env: KnowledgePipelineEnvironment, params: dict):
|
||||
return IssueParser(env, params)
|
||||
@@ -1,13 +0,0 @@
|
||||
name = "Mail.Issue"
|
||||
input.module = "local.py"
|
||||
input.params.path = "${myai_dir}/mail"
|
||||
input.params.watch = true
|
||||
parser.module = "parser.py"
|
||||
parser.params.mail_path = "${myai_dir}/mail"
|
||||
parser.params.issue_path = "${myai_dir}/mail/issue.json"
|
||||
[parser.params.root_issue]
|
||||
summary = "巴克云公司推进中的项目"
|
||||
[[parser.params.root_issue.children]]
|
||||
summary = "去中心存储项目DMC"
|
||||
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
import sys
|
||||
import os
|
||||
from knowledge import KnowledgePipelineEnvironment
|
||||
directory = os.path.dirname(__file__)
|
||||
sys.path.append(directory + '/../../../../src/component/')
|
||||
|
||||
from mail_environment import EmailSpider
|
||||
|
||||
def init(env: KnowledgePipelineEnvironment, params: dict):
|
||||
return EmailSpider(env, params)
|
||||
@@ -1,14 +0,0 @@
|
||||
name = "Mail.Sync"
|
||||
input.module = "input.py"
|
||||
[input.params]
|
||||
path = "${myai_dir}/mail"
|
||||
imap_server = "imap.qq.com"
|
||||
imap_port = 993
|
||||
address = "115620204@qq.com"
|
||||
password = "zbbjpbukeonqbjja"
|
||||
[input.params.fields]
|
||||
from = "from"
|
||||
to = "to"
|
||||
subject = "subject"
|
||||
|
||||
|
||||
@@ -1,211 +0,0 @@
|
||||
import copy
|
||||
import os
|
||||
from typing import List
|
||||
|
||||
import aiofiles
|
||||
import chardet
|
||||
import logging
|
||||
import string
|
||||
import docx2txt
|
||||
from PyPDF2 import PdfReader
|
||||
|
||||
from aios import KnowledgePipelineEnvironment, ImageObjectBuilder, DocumentObjectBuilder, KnowledgeStore, RichTextObject
|
||||
from aios.agent.agent_base import AgentPrompt
|
||||
from aios.frame.compute_kernel import ComputeKernel
|
||||
from aios.knowledge.data.writer import split_text
|
||||
from aios.proto.compute_task import ComputeTaskResult, ComputeTaskResultCode
|
||||
from aios.storage.storage import AIStorage
|
||||
from aios.utils import video_utils, image_utils
|
||||
|
||||
|
||||
class KnowledgeDirSource:
|
||||
def __init__(self, env: KnowledgePipelineEnvironment, config):
|
||||
self.env = env
|
||||
path = string.Template(config["path"]).substitute(myai_dir=AIStorage.get_instance().get_myai_dir())
|
||||
config["path"] = path
|
||||
self.config = config
|
||||
|
||||
# @classmethod
|
||||
# def user_config_items(cls):
|
||||
# return [("path", "local dir path")]
|
||||
|
||||
def path(self):
|
||||
return self.config["path"]
|
||||
|
||||
@staticmethod
|
||||
async def read_txt_file(file_path:str)->str:
|
||||
cur_encode = "utf-8"
|
||||
async with aiofiles.open(file_path,'rb') as f:
|
||||
cur_encode = chardet.detect(await f.read())['encoding']
|
||||
|
||||
async with aiofiles.open(file_path,'r',encoding=cur_encode) as f:
|
||||
return await f.read()
|
||||
|
||||
async def next(self):
|
||||
while True:
|
||||
journals = self.env.journal.latest_journals(1)
|
||||
from_time = 0
|
||||
if len(journals) == 1:
|
||||
latest_journal = journals[0]
|
||||
if latest_journal.is_finish():
|
||||
yield None
|
||||
continue
|
||||
from_time = os.path.getctime(latest_journal.get_input())
|
||||
if os.path.getmtime(self.path()) <= from_time:
|
||||
yield (None, None)
|
||||
continue
|
||||
|
||||
file_pathes = sorted(os.listdir(self.path()), key=lambda x: os.path.getctime(os.path.join(self.path(), x)))
|
||||
for rel_path in file_pathes:
|
||||
file_path = os.path.join(self.path(), rel_path)
|
||||
timestamp = os.path.getctime(file_path)
|
||||
if timestamp <= from_time:
|
||||
continue
|
||||
ext = os.path.splitext(file_path)[1].lower()
|
||||
if ext in ['.jpg', '.jpeg', '.png', '.gif', '.bmp']:
|
||||
logging.info(f"knowledge dir source found image file {file_path}")
|
||||
image = ImageObjectBuilder({}, {}, file_path).build(self.env.get_knowledge_store())
|
||||
await self.env.get_knowledge_store().insert_object(image)
|
||||
yield (image.calculate_id(), file_path)
|
||||
if ext in ['.txt']:
|
||||
logging.info(f"knowledge dir source found text file {file_path}")
|
||||
text = await self.read_txt_file(file_path)
|
||||
document = DocumentObjectBuilder({}, {}, text).build(self.env.get_knowledge_store())
|
||||
await self.env.get_knowledge_store().insert_object(document)
|
||||
yield (document.calculate_id(), file_path)
|
||||
yield (None, None)
|
||||
|
||||
|
||||
def init(env: KnowledgePipelineEnvironment, params: dict) -> KnowledgeDirSource:
|
||||
return KnowledgeDirSource(env, params)
|
||||
|
||||
|
||||
async def image_to_text(images: List[str]) -> str:
|
||||
msg_prompt = AgentPrompt()
|
||||
image_prompt = "What's in this image?"
|
||||
content = [{"type": "text", "text": image_prompt}]
|
||||
content.extend([{"type": "image_url", "image_url": {"url": image_utils.to_base64(image)}} for image in images])
|
||||
msg_prompt.messages = [{"role": "user", "content": content}]
|
||||
|
||||
resp: ComputeTaskResult = await (ComputeKernel.get_instance()
|
||||
.do_llm_completion(prompt=msg_prompt,
|
||||
resp_mode="text",
|
||||
mode_name="gpt-4-vision-preview",
|
||||
max_token=4000,
|
||||
inner_functions=None,
|
||||
timeout=None))
|
||||
if resp.result_code != ComputeTaskResultCode.OK:
|
||||
raise Exception(f"image_to_text error: {resp.result_code} msg:{resp.error_str}")
|
||||
return resp.result_str
|
||||
|
||||
|
||||
async def video_to_text(video: str) -> str:
|
||||
prompt = "These pictures are key frames extracted from the video. Please describe the content of the video based on these key frames."
|
||||
frames = video_utils.extract_frames(video, (1024, 1024))
|
||||
msg_prompt = AgentPrompt()
|
||||
content = [{"type": "text", "text": prompt}]
|
||||
content.extend([{"type": "image_url", "image_url": {"url": frame}} for frame in frames])
|
||||
msg_prompt.messages = [{"role": "user", "content": content}]
|
||||
resp: ComputeTaskResult = await (ComputeKernel.get_instance()
|
||||
.do_llm_completion(prompt=msg_prompt,
|
||||
resp_mode="text",
|
||||
mode_name="gpt-4-vision-preview",
|
||||
max_token=4000,
|
||||
inner_functions=None,
|
||||
timeout=None))
|
||||
if resp.result_code != ComputeTaskResultCode.OK:
|
||||
raise Exception(f"video_to_text error: {resp.result_code} msg:{resp.error_str}")
|
||||
return resp.result_str
|
||||
|
||||
|
||||
async def summary_document(text: str, separators: List[str]=["\n\n", "\n"]) -> str:
|
||||
chunks = split_text(text, separators=separators, chunk_size=4000, chunk_overlap=200, length_function=len)
|
||||
|
||||
prompt = AgentPrompt()
|
||||
prompt.system_message = {"role":"system","content":"Your job is to generate a summary based on the input."}
|
||||
if len(chunks) == 1:
|
||||
prompt.append(AgentPrompt(chunks[0]))
|
||||
resp = await (ComputeKernel.get_instance()
|
||||
.do_llm_completion(prompt=prompt,
|
||||
resp_mode="text",
|
||||
mode_name="gpt-4-1106-preview",
|
||||
max_token=4000,
|
||||
inner_functions=None,
|
||||
timeout=None))
|
||||
if resp.result_code != ComputeTaskResultCode.OK:
|
||||
raise Exception(f"summary_document error: {resp.result_code} msg:{resp.error_str}")
|
||||
return resp.result_str
|
||||
|
||||
segments = []
|
||||
for i, chunk in enumerate(chunks):
|
||||
seg_prompt = copy.deepcopy(prompt)
|
||||
seg_prompt.append(AgentPrompt(chunk))
|
||||
resp = await (ComputeKernel.get_instance()
|
||||
.do_llm_completion(prompt=seg_prompt,
|
||||
resp_mode="text",
|
||||
mode_name="gpt-4-1106-preview",
|
||||
max_token=4000,
|
||||
inner_functions=None,
|
||||
timeout=None))
|
||||
if resp.result_code != ComputeTaskResultCode.OK:
|
||||
raise Exception(f"summary_document error: {resp.result_code} msg:{resp.error_str}")
|
||||
segments.append(resp.result_str)
|
||||
|
||||
segments_str = "\n".join(segments)
|
||||
prompt.append(AgentPrompt(f"Please combine the summaries of the following paragraphs into one complete summary:\n{segments_str}"))
|
||||
resp = await (ComputeKernel.get_instance()
|
||||
.do_llm_completion(prompt=prompt,
|
||||
resp_mode="text",
|
||||
mode_name="gpt-4-1106-preview",
|
||||
max_token=4000,
|
||||
inner_functions=None,
|
||||
timeout=None))
|
||||
if resp.result_code != ComputeTaskResultCode.OK:
|
||||
raise Exception(f"summary_document error: {resp.result_code} msg:{resp.error_str}")
|
||||
return resp.result_str
|
||||
|
||||
|
||||
|
||||
def pdf_to_rich_text_object(pdf: str, store: KnowledgeStore) -> RichTextObject:
|
||||
base_name = os.path.basename(pdf)
|
||||
cache_path = os.path.join(AIStorage.get_instance().get_myai_dir(), "knowledge", "doc_cache", base_name)
|
||||
if not os.path.exists(cache_path):
|
||||
os.makedirs(cache_path)
|
||||
|
||||
reader = PdfReader(pdf)
|
||||
rich_text = RichTextObject()
|
||||
page_texts = []
|
||||
image_count = 0
|
||||
for page in reader.pages:
|
||||
text = page.extract_text()
|
||||
page_texts.append(text)
|
||||
for image in page.images:
|
||||
image_path = os.path.join(cache_path, f"{image_count}_{image.name}")
|
||||
with open(image_path, "wb") as f:
|
||||
f.write(image.data)
|
||||
image_object = ImageObjectBuilder({}, {}, image_path).build(store)
|
||||
rich_text.add_image(image_object)
|
||||
|
||||
document = DocumentObjectBuilder({}, {}, "".join(page_texts)).build(store)
|
||||
rich_text.add_document(document)
|
||||
|
||||
return rich_text
|
||||
|
||||
|
||||
def doc_to_rich_text_object(doc: str, store: KnowledgeStore) -> RichTextObject:
|
||||
base_name = os.path.basename(doc)
|
||||
cache_path = os.path.join(AIStorage.get_instance().get_myai_dir(), "knowledge", "doc_cache", base_name)
|
||||
if not os.path.exists(cache_path):
|
||||
os.makedirs(cache_path)
|
||||
text = docx2txt.process(doc, cache_path)
|
||||
|
||||
rich_text = RichTextObject()
|
||||
for image in os.listdir(cache_path):
|
||||
image_path = os.path.join(cache_path, image)
|
||||
image_object = ImageObjectBuilder({}, {}, image_path).build(store)
|
||||
rich_text.add_image(image_object)
|
||||
|
||||
document = DocumentObjectBuilder({}, {}, text).build(store)
|
||||
rich_text.add_document(document)
|
||||
|
||||
return rich_text
|
||||
@@ -1,101 +0,0 @@
|
||||
# define a knowledge base class
|
||||
import json
|
||||
import string
|
||||
from aios import *
|
||||
|
||||
|
||||
class EmbeddingParser:
|
||||
def __init__(self, env: KnowledgePipelineEnvironment, config: dict):
|
||||
self._default_text_model = "all-MiniLM-L6-v2"
|
||||
self._default_image_model = "clip-ViT-B-32"
|
||||
|
||||
path = string.Template(config["path"]).substitute(myai_dir=AIStorage.get_instance().get_myai_dir())
|
||||
if not os.path.exists(path):
|
||||
os.makedirs(path)
|
||||
config["path"] = path
|
||||
|
||||
self.env = env
|
||||
self.config = config
|
||||
|
||||
def get_path(self) -> str:
|
||||
return self.config["path"]
|
||||
|
||||
def __get_vector_store(self, model_name: str) -> ChromaVectorStore:
|
||||
return ChromaVectorStore(self.get_path(), model_name)
|
||||
|
||||
async def __embedding_document(self, document: DocumentObject):
|
||||
for chunk_id in document.get_chunk_list():
|
||||
chunk = self.env.get_knowledge_store().get_chunk_reader().get_chunk(chunk_id)
|
||||
if chunk is None:
|
||||
raise ValueError(f"text chunk not found: {chunk_id}")
|
||||
|
||||
text = chunk.read().decode("utf-8")
|
||||
vector = await ComputeKernel.get_instance().do_text_embedding(text, self._default_text_model)
|
||||
if vector:
|
||||
await self.__get_vector_store(self._default_text_model).insert(vector, chunk_id)
|
||||
|
||||
async def __embedding_image(self, image: ImageObject):
|
||||
# desc = {}
|
||||
# if not not image.get_meta():
|
||||
# desc["meta"] = image.get_meta()
|
||||
# if not not image.get_exif():
|
||||
# desc["exif"] = image.get_exif()
|
||||
# if not not image.get_tags():
|
||||
# desc["tags"] = image.get_tags()
|
||||
# vector = await self.compute_kernel.do_text_embedding(json.dumps(desc), self._default_text_model)
|
||||
vector = await ComputeKernel.get_instance().do_image_embedding(image.calculate_id(), self._default_image_model)
|
||||
if vector:
|
||||
await self.__get_vector_store(self._default_image_model).insert(vector, image.calculate_id())
|
||||
|
||||
async def __embedding_video(self, vedio: VideoObject):
|
||||
desc = {}
|
||||
if not not vedio.get_meta():
|
||||
desc["meta"] = vedio.get_meta()
|
||||
if not not vedio.get_info():
|
||||
desc["info"] = vedio.get_info()
|
||||
if not not vedio.get_tags():
|
||||
desc["tags"] = vedio.get_tags()
|
||||
vector = await ComputeKernel.get_instance().do_text_embedding(json.dumps(desc), self._default_text_model)
|
||||
await self.__get_vector_store(self._default_text_model).insert(vector, vedio.calculate_id())
|
||||
|
||||
async def __embedding_rich_text(self, rich_text: RichTextObject):
|
||||
for document_id in rich_text.get_documents().values():
|
||||
document = DocumentObject.decode(self.env.get_knowledge_store().get_object_store().get_object(document_id))
|
||||
await self.__embedding_document(document)
|
||||
for image_id in rich_text.get_images().values():
|
||||
image = ImageObject.decode(self.env.get_knowledge_store().get_object_store().get_object(image_id))
|
||||
await self.__embedding_image(image)
|
||||
for video_id in rich_text.get_videos().values():
|
||||
video = VideoObject.decode(self.env.get_knowledge_store().get_object_store().get_object(video_id))
|
||||
await self.__embedding_video(video)
|
||||
for rich_text_id in rich_text.get_rich_texts().values():
|
||||
rich_text = RichTextObject.decode(self.env.get_knowledge_store().get_object_store().get_object(rich_text_id))
|
||||
await self.__embedding_rich_text(rich_text)
|
||||
|
||||
async def __embedding_email(self, email: EmailObject):
|
||||
vector = await ComputeKernel.get_instance().do_text_embedding(json.dumps(email.get_desc()), self._default_text_model)
|
||||
await self.__get_vector_store(self._default_text_model).insert(vector, email.calculate_id())
|
||||
await self.__embedding_rich_text(email.get_rich_text())
|
||||
|
||||
|
||||
async def __do_embedding(self, object: KnowledgeObject):
|
||||
if object.get_object_type() == ObjectType.Document:
|
||||
await self.__embedding_document(object)
|
||||
if object.get_object_type() == ObjectType.Image:
|
||||
await self.__embedding_image(object)
|
||||
if object.get_object_type() == ObjectType.Video:
|
||||
await self.__embedding_video(object)
|
||||
if object.get_object_type() == ObjectType.RichText:
|
||||
await self.__embedding_rich_text(object)
|
||||
if object.get_object_type() == ObjectType.Email:
|
||||
await self.__embedding_email(object)
|
||||
else:
|
||||
pass
|
||||
|
||||
async def parse(self, object: ObjectID) -> str:
|
||||
obj = self.env.get_knowledge_store().load_object(object)
|
||||
await self.__do_embedding(obj)
|
||||
return str(object)
|
||||
|
||||
def init(env: KnowledgePipelineEnvironment, params: dict) -> EmbeddingParser:
|
||||
return EmbeddingParser(env, params)
|
||||
@@ -1,6 +0,0 @@
|
||||
name = "Mia"
|
||||
input.module = "input.py"
|
||||
input.params.path = "${myai_dir}/data"
|
||||
parser.module = "parser.py"
|
||||
parser.params.path = "${myai_dir}/knowledge/indices/embedding"
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
import os
|
||||
import logging
|
||||
import json
|
||||
from aios import *
|
||||
|
||||
class EmbeddingEnvironment(SimpleEnvironment):
|
||||
def __init__(self, workspace: str) -> None:
|
||||
super().__init__(workspace)
|
||||
self.path = os.path.join(AIStorage.get_instance().get_myai_dir(), "knowledge/indices/embedding")
|
||||
self._default_text_model = "all-MiniLM-L6-v2"
|
||||
self._default_image_model = "clip-ViT-B-32"
|
||||
|
||||
query_param = {
|
||||
"tokens": "key words to query",
|
||||
"types": "prefered knowledge types, one or more of [text, image]",
|
||||
"limit": "index of query result"
|
||||
}
|
||||
self.add_ai_function(SimpleAIFunction("query_knowledge",
|
||||
"vector query content from local knowledge base",
|
||||
self._query,
|
||||
query_param))
|
||||
|
||||
def __get_vector_store(self, model_name: str) -> ChromaVectorStore:
|
||||
return ChromaVectorStore(self.path, model_name)
|
||||
|
||||
async def query_objects(self, tokens: str, types: list[str], topk: int) -> [ObjectID]:
|
||||
texts = []
|
||||
if "text" in types:
|
||||
vector = await ComputeKernel.get_instance().do_text_embedding(tokens, self._default_text_model)
|
||||
texts = await self.__get_vector_store(self._default_text_model).query(vector, topk)
|
||||
images = []
|
||||
if "image" in types:
|
||||
vector = await ComputeKernel.get_instance().do_text_embedding(tokens, self._default_image_model)
|
||||
images = await self.__get_vector_store(self._default_image_model).query(vector, topk)
|
||||
return texts + images
|
||||
|
||||
|
||||
def tokens_from_objects(self, object_ids: [ObjectID]) -> list[str]:
|
||||
results = dict()
|
||||
for object_id in object_ids:
|
||||
parents = KnowledgeStore().get_relation_store().get_related_root_objects(object_id)
|
||||
# last parent is the root object
|
||||
root_object_id = parents[0] if parents else object_id
|
||||
logging.info(f"object_id: {str(object_id)} root_object_id: {str(root_object_id)}")
|
||||
if str(root_object_id) in results:
|
||||
results[str(root_object_id)].append(object_id)
|
||||
else:
|
||||
results[str(root_object_id)] = [root_object_id, object_id]
|
||||
content = ""
|
||||
result_desc = []
|
||||
for result in results.values():
|
||||
# first element in result is the root object
|
||||
root_object_id = result[0]
|
||||
if root_object_id.get_object_type() == ObjectType.Email:
|
||||
email = KnowledgeStore().load_object(root_object_id)
|
||||
desc = email.get_desc()
|
||||
desc["type"] = "email"
|
||||
desc["contents"] = []
|
||||
result_desc.append(desc)
|
||||
upper_list = desc["contents"]
|
||||
result = result[1:]
|
||||
else:
|
||||
upper_list = result_desc
|
||||
|
||||
for object_id in result:
|
||||
if object_id.get_object_type() == ObjectType.Chunk:
|
||||
upper_list.append({"type": "text", "content": KnowledgeStore().get_chunk_reader().get_chunk(object_id).read().decode("utf-8")})
|
||||
if object_id.get_object_type() == ObjectType.Image:
|
||||
# image = self.load_object(object_id)
|
||||
desc = dict()
|
||||
desc["id"] = str(object_id)
|
||||
desc["type"] = "image"
|
||||
upper_list.append(desc)
|
||||
if object_id.get_object_type() == ObjectType.Video:
|
||||
video = KnowledgeStore().load_object(object_id)
|
||||
desc = video.get_desc()
|
||||
desc["type"] = "video"
|
||||
upper_list.append(desc)
|
||||
else:
|
||||
pass
|
||||
content += json.dumps(result_desc)
|
||||
content += ".\n"
|
||||
|
||||
return content
|
||||
|
||||
async def _query(self, tokens: str, types: list[str] = ["text"], index: str=0):
|
||||
index = int(index)
|
||||
object_ids = await self.query_objects(tokens, types, 4)
|
||||
if len(object_ids) <= index:
|
||||
return "*** I have no more information for your reference.\n"
|
||||
else:
|
||||
content = "*** I have provided the following known information for your reference with json format:\n"
|
||||
return content + self.tokens_from_objects(object_ids[index:index+1])
|
||||
|
||||
def init(workspace: str) -> EmbeddingEnvironment:
|
||||
return EmbeddingEnvironment(workspace)
|
||||
@@ -1,3 +0,0 @@
|
||||
pipelines = [
|
||||
"JarvisPlus"
|
||||
]
|
||||
@@ -36,7 +36,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AgentMemory:
|
||||
def __init__(self,agent_id:str,base_dir:str,enable_knowledge_graph = True) -> None:
|
||||
def __init__(self,agent_id:str,base_dir:str,enable_knowledge_graph = False) -> None:
|
||||
self.agent_memory_base_dir = base_dir
|
||||
self.agent_id:str= agent_id
|
||||
|
||||
@@ -52,15 +52,17 @@ class AgentMemory:
|
||||
self.last_think_time : float = 0.0
|
||||
self.enable_knowledge_graph : bool = enable_knowledge_graph
|
||||
if self.enable_knowledge_graph:
|
||||
kb_desc = """The Knowledgegraph is used to store important information obtained by Agent in the conversation.Use the following ways to store information:
|
||||
/contacts/$name:Related information of the contact
|
||||
/relations/$obj1/$obj2:The relationship between obj2 and obj1
|
||||
/summary/$topic:Based on topic summary
|
||||
kb_desc = """
|
||||
The Knowledgegraph is used to store important information obtained by Agent in the conversation.Use the following ways to store information:
|
||||
- /contacts/$name:Related information of the contact
|
||||
- /relations/$obj1/$obj2:The relationship between obj2 and obj1
|
||||
- /summary/$topic:Based on topic summary
|
||||
"""
|
||||
|
||||
self.knowledge_graph = ObjFSKnowledgeGrpah(f"{self.agent_id}.memory",self.memory_db,kb_desc)
|
||||
BaseKnowledgeGraph.add_kb(self.knowledge_graph)
|
||||
self.simple_memory_sentences = None
|
||||
|
||||
else:
|
||||
self.knowledge_graph = None
|
||||
self.simple_memory_sentences : List[str] = []
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from .object import *
|
||||
from .vector import *
|
||||
#from .vector import *
|
||||
from .data import *
|
||||
from .store import KnowledgeStore
|
||||
from .core_object import *
|
||||
from .pipeline import *
|
||||
#from .pipeline import *
|
||||
from .knowledge_base import *
|
||||
@@ -1,133 +0,0 @@
|
||||
import datetime
|
||||
import sqlite3
|
||||
import os
|
||||
import logging
|
||||
from . import ObjectID, KnowledgeStore
|
||||
from enum import Enum
|
||||
|
||||
class KnowledgePipelineJournal:
|
||||
def __init__(self, time: datetime.datetime, input: str, parser: str):
|
||||
self.time = time
|
||||
self.input = input
|
||||
self.parser = parser
|
||||
|
||||
def is_finish(self) -> bool:
|
||||
return self.input is None
|
||||
|
||||
def get_input(self) -> str:
|
||||
return self.input
|
||||
|
||||
def get_parser(self) -> str:
|
||||
return self.parser
|
||||
|
||||
def __str__(self) -> str:
|
||||
if self.is_finish():
|
||||
return f"{self.time}: finished)"
|
||||
else:
|
||||
return f"{self.time}: input:{self.input}, parser:{self.parser})"
|
||||
|
||||
# init sqlite3 client
|
||||
class KnowledgePipelineJournalClient:
|
||||
def __init__(self, pipeline_path: str = None):
|
||||
if not os.path.exists(pipeline_path):
|
||||
os.makedirs(pipeline_path)
|
||||
self.journal_path = os.path.join(pipeline_path, "journal.db")
|
||||
|
||||
conn = sqlite3.connect(self.journal_path)
|
||||
conn.execute(
|
||||
'''CREATE TABLE IF NOT EXISTS journal (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
time DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
input TEXT,
|
||||
parser TEXT)'''
|
||||
)
|
||||
conn.commit()
|
||||
|
||||
def insert(self, input: str, parser: str, timestamp: datetime.datetime = None):
|
||||
timestamp = datetime.datetime.now() if timestamp is None else timestamp
|
||||
conn = sqlite3.connect(self.journal_path)
|
||||
conn.execute(
|
||||
"INSERT INTO journal (time, input, parser) VALUES (?, ?, ?)",
|
||||
(timestamp, input, parser),
|
||||
)
|
||||
conn.commit()
|
||||
|
||||
def latest_journals(self, topn) -> [KnowledgePipelineJournal]:
|
||||
conn = sqlite3.connect(self.journal_path)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT * FROM journal ORDER BY id DESC LIMIT ?", (topn,))
|
||||
return [KnowledgePipelineJournal(time, input, parser) for (_, time, input, parser) in cursor.fetchall()]
|
||||
|
||||
class KnowledgePipelineEnvironment:
|
||||
def __init__(self, pipeline_path: str):
|
||||
self.knowledge_store = KnowledgeStore()
|
||||
if not os.path.exists(pipeline_path):
|
||||
os.makedirs(pipeline_path)
|
||||
self.pipeline_path = pipeline_path
|
||||
self.journal = KnowledgePipelineJournalClient(pipeline_path)
|
||||
self.logger = logging.getLogger()
|
||||
|
||||
def get_journal(self) -> KnowledgePipelineJournalClient:
|
||||
return self.journal
|
||||
|
||||
def get_knowledge_store(self) -> KnowledgeStore:
|
||||
return self.knowledge_store
|
||||
|
||||
def get_logger(self) -> logging.Logger:
|
||||
return self.logger
|
||||
|
||||
class KnowledgePipelineState(Enum):
|
||||
INIT = 0
|
||||
RUNNING = 1
|
||||
STOPPED = 2
|
||||
FINISHED = 3
|
||||
|
||||
class NullParser:
|
||||
async def parse(self, object_id):
|
||||
return ""
|
||||
|
||||
class KnowledgePipeline:
|
||||
def __init__(self, name: str, env: KnowledgePipelineEnvironment, input_init, input_params=None, parser_init=None, parser_params=None):
|
||||
self.name = name
|
||||
self.state = KnowledgePipelineState.INIT
|
||||
self.input_init = input_init
|
||||
self.input_params = input_params
|
||||
self.parser_init = parser_init
|
||||
self.parser_params = parser_params
|
||||
self.env = env
|
||||
self.input = None
|
||||
self.parser = None
|
||||
|
||||
def get_name(self):
|
||||
return self.name
|
||||
|
||||
def get_journal(self) -> KnowledgePipelineJournalClient:
|
||||
return self.env.journal
|
||||
|
||||
async def run(self):
|
||||
if self.state == KnowledgePipelineState.INIT:
|
||||
self.input = self.input_init(self.env, self.input_params)
|
||||
if self.parser_init is None:
|
||||
self.parser = NullParser()
|
||||
else:
|
||||
self.parser = self.parser_init(self.env, self.parser_params)
|
||||
self.state = KnowledgePipelineState.RUNNING
|
||||
if self.state == KnowledgePipelineState.RUNNING:
|
||||
async for input in self.input.next():
|
||||
if input is None:
|
||||
self.state = KnowledgePipelineState.FINISHED
|
||||
self.env.journal.insert(None, None)
|
||||
return
|
||||
(object_id, input_journal) = input
|
||||
if object_id is not None:
|
||||
parser_journal = await self.parser.parse(object_id)
|
||||
self.env.journal.insert(input_journal, parser_journal)
|
||||
else:
|
||||
return
|
||||
if self.state == KnowledgePipelineState.STOPPED:
|
||||
return
|
||||
if self.state == KnowledgePipelineState.FINISHED:
|
||||
return
|
||||
|
||||
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
from .vector_base import VectorBase
|
||||
from .chroma_store import ChromaVectorStore
|
||||
@@ -1,51 +0,0 @@
|
||||
from .vector_base import VectorBase
|
||||
from ..object import ObjectID
|
||||
import chromadb
|
||||
import logging
|
||||
import os
|
||||
|
||||
|
||||
class ChromaVectorStore(VectorBase):
|
||||
def __init__(self, root_dir, model_name: str) -> None:
|
||||
super().__init__(model_name)
|
||||
|
||||
logging.info(
|
||||
"will init chroma vector store, model={}".format(model_name)
|
||||
)
|
||||
|
||||
directory = os.path.join(root_dir, "vector")
|
||||
logging.info("will use vector store: {}".format(directory))
|
||||
|
||||
client = chromadb.PersistentClient(
|
||||
path=directory, settings=chromadb.Settings(anonymized_telemetry=False)
|
||||
)
|
||||
# client = chromadb.Client()
|
||||
|
||||
collection_name = "coll_{}".format(model_name)
|
||||
logging.info("will init chroma colletion: %s", collection_name)
|
||||
|
||||
collection = client.get_or_create_collection(collection_name)
|
||||
self.collection = collection
|
||||
|
||||
async def insert(self, vector: [float], id: ObjectID):
|
||||
logging.info(f"will insert vector: {len(vector)} id: {str(id)}")
|
||||
logging.debug(f"vector is {vector}")
|
||||
self.collection.add(
|
||||
embeddings=vector,
|
||||
ids=str(id),
|
||||
)
|
||||
|
||||
async def query(self, vector: [float], top_k: int) -> [ObjectID]:
|
||||
ret = self.collection.query(
|
||||
query_embeddings=vector,
|
||||
n_results=top_k,
|
||||
)
|
||||
logging.info(f"query result {ret}")
|
||||
if len(ret['ids']) == 0:
|
||||
return []
|
||||
return list(map(ObjectID.from_base58, ret["ids"][0]))
|
||||
|
||||
async def delete(self, id: ObjectID):
|
||||
self.collection.delete(
|
||||
ids=id,
|
||||
)
|
||||
@@ -1,16 +0,0 @@
|
||||
# import the ObjectID class
|
||||
from ..object import ObjectID
|
||||
|
||||
# define a vector base class
|
||||
class VectorBase:
|
||||
def __init__(self, model_name) -> None:
|
||||
self.model_name = model_name
|
||||
|
||||
async def insert(self, vector: [float], id: ObjectID):
|
||||
pass
|
||||
|
||||
async def query(self, vector: [float], top_k: int) -> [ObjectID]:
|
||||
pass
|
||||
|
||||
async def delete(self, id: ObjectID):
|
||||
pass
|
||||
@@ -61,7 +61,7 @@ class AgentMsg:
|
||||
self.mentions:[] = None #use in group chat only
|
||||
#self.title:str = None
|
||||
self.body:str = None
|
||||
self.body_mime:str = None #//default is "text/plain",encode is utf8
|
||||
self.body_mime:str = "text/plain" #//default is "text/plain",encode is utf8
|
||||
|
||||
#type is call / action
|
||||
self.func_name = None
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
from .local_document import LocalKnowledgeBase, ScanLocalDocument, ParseLocalDocument
|
||||
#from .local_document import LocalKnowledgeBase, ScanLocalDocument, ParseLocalDocument
|
||||
from .local_file_system import FilesystemEnvironment
|
||||
from .shell import ShellEnvironment
|
||||
@@ -9,7 +9,7 @@ import aiofiles
|
||||
from urllib.parse import urlparse
|
||||
from typing import Optional
|
||||
|
||||
from aios import KnowledgeStore, ObjectType
|
||||
#from aios import KnowledgeStore, ObjectType
|
||||
from aios.frame.tunnel import AgentTunnel
|
||||
from aios.proto.agent_msg import AgentMsg, AgentMsgType
|
||||
import discord
|
||||
@@ -165,26 +165,26 @@ class DiscordTunnel(AgentTunnel):
|
||||
if len(resp_msg.body) < 1:
|
||||
return
|
||||
|
||||
knownledge_object = KnowledgeStore().parse_object_in_message(resp_msg.body)
|
||||
if knownledge_object is not None:
|
||||
if knownledge_object.get_object_type() == ObjectType.Image:
|
||||
image = KnowledgeStore().bytes_from_object(knownledge_object)
|
||||
try:
|
||||
async with aiofiles.open("image.jpg", "wb") as f:
|
||||
await f.write(image)
|
||||
await message.channel.send(file=discord.File("image.jpg"))
|
||||
except Exception as e:
|
||||
logger.error(f"save image error:{e}")
|
||||
logger.exception(e)
|
||||
return
|
||||
else:
|
||||
pos = resp_msg.body.find("audio file")
|
||||
if pos != -1:
|
||||
audio_file = resp_msg.body[pos+11:].strip()
|
||||
if audio_file.startswith("\""):
|
||||
audio_file = audio_file[1:-1]
|
||||
await message.channel.send(file=discord.File(audio_file))
|
||||
return
|
||||
# knownledge_object = KnowledgeStore().parse_object_in_message(resp_msg.body)
|
||||
# if knownledge_object is not None:
|
||||
# if knownledge_object.get_object_type() == ObjectType.Image:
|
||||
# image = KnowledgeStore().bytes_from_object(knownledge_object)
|
||||
# try:
|
||||
# async with aiofiles.open("image.jpg", "wb") as f:
|
||||
# await f.write(image)
|
||||
# await message.channel.send(file=discord.File("image.jpg"))
|
||||
# except Exception as e:
|
||||
# logger.error(f"save image error:{e}")
|
||||
# logger.exception(e)
|
||||
# return
|
||||
# else:
|
||||
# pos = resp_msg.body.find("audio file")
|
||||
# if pos != -1:
|
||||
# audio_file = resp_msg.body[pos+11:].strip()
|
||||
# if audio_file.startswith("\""):
|
||||
# audio_file = audio_file[1:-1]
|
||||
# await message.channel.send(file=discord.File(audio_file))
|
||||
# return
|
||||
await message.channel.send(resp_msg.body)
|
||||
else:
|
||||
if resp_msg.is_image_msg():
|
||||
|
||||
@@ -12,7 +12,7 @@ import aiohttp
|
||||
from slack_bolt.adapter.socket_mode.websockets import AsyncSocketModeHandler
|
||||
from slack_bolt.app.async_app import AsyncApp
|
||||
|
||||
from aios import KnowledgeStore, ObjectType
|
||||
#from aios import KnowledgeStore, ObjectType
|
||||
from aios.frame.tunnel import AgentTunnel
|
||||
from aios.proto.agent_msg import AgentMsg, AgentMsgType
|
||||
from aios.storage.storage import AIStorage
|
||||
@@ -189,26 +189,26 @@ class SlackTunnel(AgentTunnel):
|
||||
if len(resp_msg.body) < 1:
|
||||
return
|
||||
|
||||
knownledge_object = KnowledgeStore().parse_object_in_message(resp_msg.body)
|
||||
if knownledge_object is not None:
|
||||
if knownledge_object.get_object_type() == ObjectType.Image:
|
||||
image = KnowledgeStore().bytes_from_object(knownledge_object)
|
||||
try:
|
||||
async with aiofiles.open("image.jpg", "wb") as f:
|
||||
await f.write(image)
|
||||
await app.client.files_upload_v2(channel=event["channel"], file="image.jpg")
|
||||
except Exception as e:
|
||||
logger.error(f"save image error:{e}")
|
||||
logger.exception(e)
|
||||
return
|
||||
else:
|
||||
pos = resp_msg.body.find("audio file")
|
||||
if pos != -1:
|
||||
audio_file = resp_msg.body[pos+11:].strip()
|
||||
if audio_file.startswith("\""):
|
||||
audio_file = audio_file[1:-1]
|
||||
await app.client.files_upload_v2(channel=event["channel"], file=audio_file)
|
||||
return
|
||||
# knownledge_object = KnowledgeStore().parse_object_in_message(resp_msg.body)
|
||||
# if knownledge_object is not None:
|
||||
# if knownledge_object.get_object_type() == ObjectType.Image:
|
||||
# image = KnowledgeStore().bytes_from_object(knownledge_object)
|
||||
# try:
|
||||
# async with aiofiles.open("image.jpg", "wb") as f:
|
||||
# await f.write(image)
|
||||
# await app.client.files_upload_v2(channel=event["channel"], file="image.jpg")
|
||||
# except Exception as e:
|
||||
# logger.error(f"save image error:{e}")
|
||||
# logger.exception(e)
|
||||
# return
|
||||
# else:
|
||||
# pos = resp_msg.body.find("audio file")
|
||||
# if pos != -1:
|
||||
# audio_file = resp_msg.body[pos+11:].strip()
|
||||
# if audio_file.startswith("\""):
|
||||
# audio_file = audio_file[1:-1]
|
||||
# await app.client.files_upload_v2(channel=event["channel"], file=audio_file)
|
||||
# return
|
||||
await app.client.chat_postMessage(channel=event["channel"], text=resp_msg.body)
|
||||
else:
|
||||
if resp_msg.is_image_msg():
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
from .local_st_compute_node import *
|
||||
@@ -1,212 +0,0 @@
|
||||
import logging
|
||||
import requests
|
||||
from typing import Optional, List
|
||||
from pydantic import BaseModel
|
||||
from typing import Union
|
||||
from PIL import Image
|
||||
import io
|
||||
|
||||
from aios import ComputeTask, ComputeTaskResult, ComputeTaskState, ComputeTaskType,ComputeTaskResultCode,ComputeNode,AIStorage,UserConfig,ObjectID,Queue_ComputeNode
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class LocalSentenceTransformer_Text_ComputeNode(Queue_ComputeNode):
|
||||
# For valid pretrained models, see https://www.sbert.net/docs/pretrained_models.html
|
||||
def __init__(self, model_name: str = "all-MiniLM-L6-v2"):
|
||||
super().__init__()
|
||||
|
||||
self.node_id = "local_sentence_transformer_text_embedding_node"
|
||||
self.model_name = model_name
|
||||
self.model = None
|
||||
|
||||
def initial(self) -> bool:
|
||||
logger.info(
|
||||
f"LocalSentenceTransformer_Text_ComputeNode init, model_name: {self.model_name}"
|
||||
)
|
||||
|
||||
assert self.model_name is not None
|
||||
assert self.model is None
|
||||
try:
|
||||
from sentence_transformers import SentenceTransformer
|
||||
|
||||
self.model = SentenceTransformer(self.model_name)
|
||||
except Exception as err:
|
||||
logger.error(f"load model {self.model} failed: {err}")
|
||||
return False
|
||||
self.start()
|
||||
return True
|
||||
|
||||
async def execute_task(self, task: ComputeTask) :
|
||||
result = ComputeTaskResult()
|
||||
result.result_code = ComputeTaskResultCode.ERROR
|
||||
result.set_from_task(task)
|
||||
result.worker_id = self.node_id
|
||||
try:
|
||||
# logger.debug(f"LocalSentenceTransformer_Text_ComputeNode task: {task}")
|
||||
if task.task_type == ComputeTaskType.TEXT_EMBEDDING:
|
||||
input = task.params["input"]
|
||||
logger.debug(
|
||||
f"LocalSentenceTransformer_Text_ComputeNode task input: {input}"
|
||||
)
|
||||
sentence_embeddings = self.model.encode(input, show_progress_bar=False).tolist()
|
||||
# logger.debug(f"LocalSentenceTransformer_Text_ComputeNode task sentence_embeddings: {sentence_embeddings}")
|
||||
result.result_code = ComputeTaskResultCode.OK
|
||||
result.result["content"] = sentence_embeddings
|
||||
|
||||
else:
|
||||
result.error_str = f"unsupport embedding task type: {task.task_type}"
|
||||
except Exception as err:
|
||||
import traceback
|
||||
|
||||
logger.error(f"{traceback.format_exc()}, error: {err}")
|
||||
result.error_str = f"{traceback.format_exc()}, error: {err}"
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def display(self) -> str:
|
||||
return f"LocalSentenceTransformer_Text_ComputeNode: {self.node_id}, {self.model_name}"
|
||||
|
||||
def get_capacity(self):
|
||||
pass
|
||||
|
||||
def is_support(self, task: ComputeTask) -> bool:
|
||||
return task.task_type == ComputeTaskType.TEXT_EMBEDDING and task.params["model_name"] == "all-MiniLM-L6-v2"
|
||||
|
||||
def is_local(self) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
class LocalSentenceTransformer_Image_ComputeNode(Queue_ComputeNode):
|
||||
# For valid pretrained models, see https://www.sbert.net/docs/pretrained_models.html
|
||||
def __init__(
|
||||
self,
|
||||
model_name: str = "clip-ViT-B-32",
|
||||
multi_model_name: str = "clip-ViT-B-32-multilingual-v1",
|
||||
):
|
||||
super().__init__()
|
||||
|
||||
self.node_id = "local_sentence_transformer_image_embedding_node"
|
||||
self.model_name = model_name
|
||||
self.multi_model_name = multi_model_name
|
||||
self.model = None
|
||||
self.multi_model = None
|
||||
|
||||
def initial(self) -> bool:
|
||||
logger.info(
|
||||
f"LocalSentenceTransformer_Image_ComputeNode init, model_name: {self.model_name} {self.multi_model_name}"
|
||||
)
|
||||
|
||||
assert self.model_name is not None
|
||||
assert self.multi_model_name is not None
|
||||
assert self.model is None
|
||||
assert self.multi_model is None
|
||||
|
||||
try:
|
||||
from sentence_transformers import SentenceTransformer
|
||||
|
||||
self.model = SentenceTransformer(self.model_name)
|
||||
self.multi_model = SentenceTransformer(self.multi_model_name)
|
||||
except Exception as err:
|
||||
logger.error(f"load model {self.model} failed: {err}")
|
||||
return False
|
||||
self.start()
|
||||
return True
|
||||
|
||||
def _load_image(self, source: Union[ObjectID, bytes]) -> Optional[Image]:
|
||||
image_data = None
|
||||
if isinstance(source, ObjectID):
|
||||
from aios import KnowledgeStore, ImageObject
|
||||
|
||||
buf = KnowledgeStore().get_object_store().get_object(source)
|
||||
if buf is None:
|
||||
logger.error(f"load image object but not found! {source}")
|
||||
return None
|
||||
|
||||
try:
|
||||
image_obj = ImageObject.decode(buf)
|
||||
except Exception as err:
|
||||
logger.error(f"decode ImageObject from buffer failed: {source}, {err}")
|
||||
return None
|
||||
|
||||
file_size = image_obj.get_file_size()
|
||||
# print(f"got image object: {source.to_base58()}, size: {file_size}")
|
||||
|
||||
image_data = (
|
||||
KnowledgeStore()
|
||||
.get_chunk_reader()
|
||||
.read_chunk_list_to_single_bytes(image_obj.get_chunk_list())
|
||||
)
|
||||
|
||||
elif isinstance(source, bytes):
|
||||
image_data = source
|
||||
else:
|
||||
logger.error(f"unsupport image source type: {type(source)}, {source}")
|
||||
return None
|
||||
|
||||
try:
|
||||
img = Image.open(io.BytesIO(image_data))
|
||||
|
||||
return img
|
||||
except Exception as err:
|
||||
logger.error(f"load image from buffer failed: {source}, {err}")
|
||||
return None
|
||||
|
||||
async def execute_task(
|
||||
self, task: ComputeTask
|
||||
) -> ComputeTaskResult:
|
||||
result = ComputeTaskResult()
|
||||
result.result_code = ComputeTaskResultCode.ERROR
|
||||
result.set_from_task(task)
|
||||
result.worker_id = self.node_id
|
||||
try:
|
||||
# logger.debug(f"LocalSentenceTransformer_Text_ComputeNode task: {task}")
|
||||
if task.task_type == ComputeTaskType.TEXT_EMBEDDING:
|
||||
input = task.params["input"]
|
||||
logger.debug(
|
||||
f"LocalSentenceTransformer_Text_ComputeNode task text input: {input}"
|
||||
)
|
||||
sentence_embeddings = self.multi_model.encode(input, show_progress_bar=False).tolist()
|
||||
# logger.debug(f"LocalSentenceTransformer_Text_ComputeNode task sentence_embeddings: {sentence_embeddings}")
|
||||
result.result_code = ComputeTaskResultCode.OK
|
||||
result.result["content"] = sentence_embeddings
|
||||
|
||||
elif task.task_type == ComputeTaskType.IMAGE_EMBEDDING:
|
||||
input = task.params["input"]
|
||||
logger.debug(
|
||||
f"LocalSentenceTransformer_Image_ComputeNode task image input: {input}"
|
||||
)
|
||||
|
||||
img = self._load_image(input)
|
||||
if img is None:
|
||||
result.error_str = f"load image failed: {input}"
|
||||
return result
|
||||
|
||||
sentence_embeddings = self.model.encode(img, show_progress_bar=False).tolist()
|
||||
result.result_code = ComputeTaskResultCode.OK
|
||||
result.result["content"] = sentence_embeddings
|
||||
else:
|
||||
result.error_str = f"unsupport embedding task type: {task.task_type}"
|
||||
except Exception as err:
|
||||
import traceback
|
||||
|
||||
logger.error(f"{traceback.format_exc()}, error: {err}")
|
||||
result.error_str = f"{traceback.format_exc()}, error: {err}"
|
||||
|
||||
|
||||
return result
|
||||
|
||||
def display(self) -> str:
|
||||
return f"LocalSentenceTransformer_Image_ComputeNode: {self.node_id}, {self.model_name}"
|
||||
|
||||
def get_capacity(self):
|
||||
pass
|
||||
|
||||
def is_support(self, task: ComputeTask) -> bool:
|
||||
return (
|
||||
(task.task_type == ComputeTaskType.TEXT_EMBEDDING and task.params["model_name"] == "clip-ViT-B-32")
|
||||
or task.task_type == ComputeTaskType.IMAGE_EMBEDDING
|
||||
)
|
||||
|
||||
def is_local(self) -> bool:
|
||||
return True
|
||||
+66
-58
@@ -12,7 +12,7 @@ from telegram import Bot
|
||||
from telegram.ext import Updater
|
||||
from telegram.error import Forbidden, NetworkError
|
||||
|
||||
from aios import ObjectType, KnowledgeStore,AgentTunnel,AIStorage,ContactManager,Contact,AgentMsg,AgentMsgType
|
||||
from aios import AgentTunnel,AIStorage,ContactManager,Contact,AgentMsg,AgentMsgType
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -160,6 +160,68 @@ class TelegramTunnel(AgentTunnel):
|
||||
if not os.path.exists(path):
|
||||
os.makedirs(path)
|
||||
return path
|
||||
|
||||
async def conver_agent_msg_to_tg_msg(self,resp_msg:AgentMsg,update: Update):
|
||||
|
||||
if resp_msg.body_mime is None:
|
||||
if resp_msg.body is None:
|
||||
return
|
||||
|
||||
if len(resp_msg.body) < 1:
|
||||
await update.message.reply_text("")
|
||||
return
|
||||
|
||||
# knowledge_object = KnowledgeStore().parse_object_in_message(resp_msg.body)
|
||||
# knowledge_object = None
|
||||
# if knowledge_object is not None:
|
||||
# if knowledge_object.get_object_type() == ObjectType.Image:
|
||||
# image = KnowledgeStore().bytes_from_object(knowledge_object)
|
||||
# try:
|
||||
# async with aiofiles.open("tg_send_temp.png", mode='wb') as local_file:
|
||||
# if local_file:
|
||||
# await local_file.write(image)
|
||||
# await update.message.reply_photo("tg_send_temp.png")
|
||||
# except Exception as e:
|
||||
# logger.error(f"save image error: {e}")
|
||||
# return
|
||||
# else:
|
||||
# pos = resp_msg.body.find("audio file")
|
||||
# if pos != -1:
|
||||
# audio_file = resp_msg.body[pos+11:].strip()
|
||||
# if audio_file.startswith("\""):
|
||||
# audio_file = audio_file[1:-1]
|
||||
# await update.message.reply_voice(audio_file)
|
||||
# return
|
||||
await update.message.reply_text(resp_msg.body)
|
||||
else:
|
||||
if resp_msg.is_image_msg():
|
||||
text, images = resp_msg.get_image_body()
|
||||
if text is not None:
|
||||
await update.message.reply_text(text)
|
||||
for image in images:
|
||||
if os.path.exists(image):
|
||||
await update.message.reply_photo(image)
|
||||
else:
|
||||
await update.message.reply_text(image)
|
||||
elif resp_msg.is_video_msg():
|
||||
text, video_file = resp_msg.get_video_body()
|
||||
if text is not None:
|
||||
await update.message.reply_text(text)
|
||||
if os.path.exists(video_file):
|
||||
await update.message.reply_video(video_file)
|
||||
else:
|
||||
await update.message.reply_text(video_file)
|
||||
elif resp_msg.is_audio_msg():
|
||||
text, audio_file = resp_msg.get_audio_body()
|
||||
if text is not None:
|
||||
await update.message.reply_text(text)
|
||||
|
||||
if os.path.exists(audio_file):
|
||||
await update.message.reply_voice(audio_file)
|
||||
else:
|
||||
await update.message.reply_text(audio_file)
|
||||
else:
|
||||
await update.message.reply_text(resp_msg.body)
|
||||
|
||||
async def conver_tg_msg_to_agent_msg(self,message:Message) -> AgentMsg:
|
||||
agent_msg = AgentMsg()
|
||||
@@ -246,6 +308,7 @@ class TelegramTunnel(AgentTunnel):
|
||||
|
||||
return False
|
||||
|
||||
# main entry for telegram message
|
||||
async def on_message(self, bot:Bot, update: Update) -> None:
|
||||
message = update.message
|
||||
logger.info(f"on_message: {message.message_id} from {message.from_user.username} ({update.effective_user.username}) to {message.chat.title}({message.chat.id})")
|
||||
@@ -312,63 +375,8 @@ class TelegramTunnel(AgentTunnel):
|
||||
if resp_msg is None:
|
||||
await update.message.reply_text(f"System Error: Timeout,{self.target_id} no resopnse! Please check logs/aios.log for more details!")
|
||||
else:
|
||||
if resp_msg.body_mime is None:
|
||||
if resp_msg.body is None:
|
||||
return
|
||||
await self.conver_agent_msg_to_tg_msg(resp_msg,update)
|
||||
|
||||
if len(resp_msg.body) < 1:
|
||||
await update.message.reply_text("")
|
||||
return
|
||||
|
||||
knowledge_object = KnowledgeStore().parse_object_in_message(resp_msg.body)
|
||||
if knowledge_object is not None:
|
||||
if knowledge_object.get_object_type() == ObjectType.Image:
|
||||
image = KnowledgeStore().bytes_from_object(knowledge_object)
|
||||
try:
|
||||
async with aiofiles.open("tg_send_temp.png", mode='wb') as local_file:
|
||||
if local_file:
|
||||
await local_file.write(image)
|
||||
await update.message.reply_photo("tg_send_temp.png")
|
||||
except Exception as e:
|
||||
logger.error(f"save image error: {e}")
|
||||
return
|
||||
else:
|
||||
pos = resp_msg.body.find("audio file")
|
||||
if pos != -1:
|
||||
audio_file = resp_msg.body[pos+11:].strip()
|
||||
if audio_file.startswith("\""):
|
||||
audio_file = audio_file[1:-1]
|
||||
await update.message.reply_voice(audio_file)
|
||||
return
|
||||
await update.message.reply_text(resp_msg.body)
|
||||
else:
|
||||
if resp_msg.is_image_msg():
|
||||
text, images = resp_msg.get_image_body()
|
||||
if text is not None:
|
||||
await update.message.reply_text(text)
|
||||
for image in images:
|
||||
if os.path.exists(image):
|
||||
await update.message.reply_photo(image)
|
||||
else:
|
||||
await update.message.reply_text(image)
|
||||
elif resp_msg.is_video_msg():
|
||||
text, video_file = resp_msg.get_video_body()
|
||||
if text is not None:
|
||||
await update.message.reply_text(text)
|
||||
if os.path.exists(video_file):
|
||||
await update.message.reply_video(video_file)
|
||||
else:
|
||||
await update.message.reply_text(video_file)
|
||||
elif resp_msg.is_audio_msg():
|
||||
text, audio_file = resp_msg.get_audio_body()
|
||||
if text is not None:
|
||||
await update.message.reply_text(text)
|
||||
|
||||
if os.path.exists(audio_file):
|
||||
await update.message.reply_voice(audio_file)
|
||||
else:
|
||||
await update.message.reply_text(audio_file)
|
||||
else:
|
||||
await update.message.reply_text(resp_msg.body)
|
||||
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,159 @@
|
||||
aiofiles>=23.2.1
|
||||
aiohttp>=3.8.5
|
||||
aioimaplib>=1.0.1
|
||||
aiosignal>=1.3.1
|
||||
aiosmtplib>=2.0.2
|
||||
anyio>=4.0.0
|
||||
async-timeout>=4.0.3
|
||||
attrs>=23.1.0
|
||||
backoff>=2.2.1
|
||||
base36>=0.1.1
|
||||
base58>=2.1.1
|
||||
beautifulsoup4>=4.12.2
|
||||
cachetools>=5.3.1
|
||||
certifi>=2023.7.22
|
||||
charset-normalizer>=3.2.0
|
||||
chroma-hnswlib>=0.7.1
|
||||
chromadb>=0.4.0
|
||||
click>=8.1.7
|
||||
colorama>=0.4.6
|
||||
coloredlogs>=15.0.1
|
||||
decorator>=4.4.2
|
||||
fastapi
|
||||
filelock>=3.12.3
|
||||
flatbuffers>=23.5.26
|
||||
frozenlist>=1.4.0
|
||||
fsspec>=2023.9.0
|
||||
google>=3.0.0
|
||||
google-api-core>=2.11.1
|
||||
google-auth>=2.23.0
|
||||
google-cloud>=0.34.0
|
||||
google-cloud-texttospeech>=2.14.1
|
||||
googleapis-common-protos>=1.60.0
|
||||
h11>=0.14.0
|
||||
httpcore>=0.17.3
|
||||
httptools>=0.6.0
|
||||
httpx>=0.24.1
|
||||
huggingface-hub>=0.16.4
|
||||
humanfriendly>=10.0
|
||||
idna>=3.4
|
||||
imageio>=2.31.3
|
||||
imageio-ffmpeg>=0.4.8
|
||||
importlib-resources>=6.0.1
|
||||
mail-parser>=3.15.0
|
||||
monotonic>=1.6
|
||||
moviepy>=1.0.0
|
||||
mpmath>=1.3.0
|
||||
multidict>=6.0.4
|
||||
numpy>=1.25.2
|
||||
onnxruntime>=1.15.1
|
||||
|
||||
overrides>=7.4.0
|
||||
packaging>=23.1
|
||||
pandas>=2.1.0
|
||||
Pillow>=10.0.0
|
||||
posthog>=3.0.2
|
||||
proglog>=0.1.10
|
||||
prompt-toolkit>=3.0.39
|
||||
proto-plus>=1.22.3
|
||||
pulsar-client>=3.3.0
|
||||
pyasn1>=0.5.0
|
||||
pyasn1-modules>=0.3.0
|
||||
pydantic
|
||||
PyPika>=0.48.9
|
||||
pyreadline3>=3.4.1
|
||||
python-dateutil>=2.8.2
|
||||
python-dotenv>=1.0.0
|
||||
python-telegram-bot>=20.5
|
||||
pytz>=2023.3.post1
|
||||
PyYAML>=6.0.1
|
||||
requests>=2.31.0
|
||||
rsa>=4.9
|
||||
simplejson>=3.19.1
|
||||
six>=1.16.0
|
||||
sniffio>=1.3.0
|
||||
soupsieve>=2.5
|
||||
starlette>=0.27.0
|
||||
sympy>=1.12
|
||||
tokenizers>=0.14.0
|
||||
toml>=0.10.0
|
||||
protobuf
|
||||
grpcio
|
||||
grpcio-status
|
||||
h11==0.14.0
|
||||
httpcore==0.17.3
|
||||
httptools==0.6.0
|
||||
httpx==0.24.1
|
||||
huggingface-hub==0.16.4
|
||||
humanfriendly==10.0
|
||||
idna==3.4
|
||||
imageio==2.31.3
|
||||
imageio-ffmpeg==0.4.8
|
||||
importlib-resources==6.0.1
|
||||
mail-parser==3.15.0
|
||||
monotonic==1.6
|
||||
moviepy==1.0.0
|
||||
mpmath==1.3.0
|
||||
multidict==6.0.4
|
||||
numpy==1.25.2
|
||||
onnxruntime==1.15.1
|
||||
overrides==7.4.0
|
||||
packaging==23.1
|
||||
pandas==2.1.0
|
||||
Pillow==10.0.0
|
||||
posthog==3.0.2
|
||||
proglog==0.1.10
|
||||
prompt-toolkit==3.0.39
|
||||
proto-plus==1.22.3
|
||||
protobuf
|
||||
pulsar-client==3.3.0
|
||||
pyasn1==0.5.0
|
||||
pyasn1-modules==0.3.0
|
||||
pydantic==1.10.12
|
||||
PyPika==0.48.9
|
||||
pyreadline3==3.4.1
|
||||
python-dateutil==2.8.2
|
||||
python-dotenv==1.0.0
|
||||
python-telegram-bot==20.5
|
||||
pytz==2023.3.post1
|
||||
PyYAML==6.0.1
|
||||
requests==2.31.0
|
||||
rsa==4.9
|
||||
simplejson==3.19.1
|
||||
six==1.16.0
|
||||
sniffio==1.3.0
|
||||
soupsieve==2.5
|
||||
starlette==0.27.0
|
||||
sympy==1.12
|
||||
telegram==0.0.1
|
||||
tokenizers==0.14.0
|
||||
toml==0.10.0
|
||||
pysocks
|
||||
chardet
|
||||
pydub
|
||||
aiosqlite
|
||||
python-telegram-bot
|
||||
pydub
|
||||
stability_sdk
|
||||
sentence-transformers==2.2.2
|
||||
tiktoken
|
||||
markdown
|
||||
PyPDF2
|
||||
srt
|
||||
webvtt-py
|
||||
openai
|
||||
docker
|
||||
generic_escape
|
||||
duckduckgo-search
|
||||
SQLAlchemy
|
||||
mysqlclient
|
||||
psycopg2-binary
|
||||
pyodbc
|
||||
oracledb
|
||||
html2text
|
||||
docx2txt
|
||||
opencv-python
|
||||
discord.py
|
||||
slack_bolt
|
||||
wget
|
||||
moviepy
|
||||
@@ -38,16 +38,16 @@ from google_node import *
|
||||
from llama_node import *
|
||||
from openai_node import *
|
||||
from sd_node import *
|
||||
from st_node import *
|
||||
|
||||
from agent_manager import AgentManager
|
||||
from workflow_manager import WorkflowManager
|
||||
from knowledge_manager import KnowledgePipelineManager
|
||||
#from knowledge_manager import KnowledgePipelineManager
|
||||
from tg_tunnel import TelegramTunnel
|
||||
from email_tunnel import EmailTunnel
|
||||
from discord_tunnel import DiscordTunnel
|
||||
from slack_tunnel import SlackTunnel
|
||||
from common_environment import LocalKnowledgeBase, FilesystemEnvironment, ShellEnvironment, ScanLocalDocument, ParseLocalDocument
|
||||
from common_environment import FilesystemEnvironment, ShellEnvironment
|
||||
#from common_environment import ScanLocalDocument, ParseLocalDocument
|
||||
|
||||
from compute_node_config import *
|
||||
|
||||
@@ -214,17 +214,17 @@ class AIOS_Shell:
|
||||
|
||||
|
||||
|
||||
local_st_text_compute_node = LocalSentenceTransformer_Text_ComputeNode()
|
||||
if local_st_text_compute_node.initial() is not True:
|
||||
logger.error("local sentence transformer text embedding node initial failed!")
|
||||
else:
|
||||
ComputeKernel.get_instance().add_compute_node(local_st_text_compute_node)
|
||||
# local_st_text_compute_node = LocalSentenceTransformer_Text_ComputeNode()
|
||||
# if local_st_text_compute_node.initial() is not True:
|
||||
# logger.error("local sentence transformer text embedding node initial failed!")
|
||||
# else:
|
||||
# ComputeKernel.get_instance().add_compute_node(local_st_text_compute_node)
|
||||
|
||||
local_st_image_compute_node = LocalSentenceTransformer_Image_ComputeNode()
|
||||
if local_st_image_compute_node.initial() is not True:
|
||||
logger.error("local sentence transformer image embedding node initial failed!")
|
||||
else:
|
||||
ComputeKernel.get_instance().add_compute_node(local_st_image_compute_node)
|
||||
# local_st_image_compute_node = LocalSentenceTransformer_Image_ComputeNode()
|
||||
# if local_st_image_compute_node.initial() is not True:
|
||||
# logger.error("local sentence transformer image embedding node initial failed!")
|
||||
# else:
|
||||
# ComputeKernel.get_instance().add_compute_node(local_st_image_compute_node)
|
||||
|
||||
|
||||
await ComputeKernel.get_instance().start()
|
||||
@@ -233,12 +233,12 @@ class AIOS_Shell:
|
||||
#AIBus().get_default_bus().register_message_handler(self.username,self._user_process_msg)
|
||||
|
||||
|
||||
pipelines = KnowledgePipelineManager.initial(os.path.join(AIStorage().get_instance().get_myai_dir(), "knowledge/pipelines"))
|
||||
pipelines.register_input("scan_local", ScanLocalDocument)
|
||||
pipelines.register_parser("parse_local", ParseLocalDocument)
|
||||
pipelines.load_dir(os.path.join(AIStorage().get_instance().get_system_app_dir(), "knowledge_pipelines"))
|
||||
pipelines.load_dir(os.path.join(AIStorage().get_instance().get_myai_dir(), "knowledge_pipelines"))
|
||||
asyncio.create_task(pipelines.run())
|
||||
#pipelines = KnowledgePipelineManager.initial(os.path.join(AIStorage().get_instance().get_myai_dir(), "knowledge/pipelines"))
|
||||
#pipelines.register_input("scan_local", ScanLocalDocument)
|
||||
#pipelines.register_parser("parse_local", ParseLocalDocument)
|
||||
#pipelines.load_dir(os.path.join(AIStorage().get_instance().get_system_app_dir(), "knowledge_pipelines"))
|
||||
#pipelines.load_dir(os.path.join(AIStorage().get_instance().get_myai_dir(), "knowledge_pipelines"))
|
||||
#asyncio.create_task(pipelines.run())
|
||||
|
||||
TelegramTunnel.register_to_loader()
|
||||
EmailTunnel.register_to_loader()
|
||||
|
||||
Reference in New Issue
Block a user