tina-python 0.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
tina/tina.py ADDED
@@ -0,0 +1,211 @@
1
+ """
2
+ Tina is in your Computer!
3
+ 启动你的tina吧!
4
+ 基于tina.Agent的智能体
5
+ 自动执行tina的各种操作
6
+ """
7
+ import threading
8
+ import os
9
+ import time
10
+ import random
11
+ from tina.core.manage import TinaFolderManager
12
+ from tina.core.prompt import Prompt
13
+ from tina.core.tools import Tools
14
+ from tina.RAG.Embedding.docToVec import docToVec
15
+ from tina.Agent import Agent
16
+
17
+ class Tina:
18
+ def __init__(self, path:str = None, LLM=None, tools:type = None,toolsLib:str = None, stream:bool = True, timeout:int = 600,embeding_model:str = None,isSystem:bool = False, isRAG:bool = False, is_tool_call_permission:bool=False):
19
+ """
20
+ 初始化你的控制台tina
21
+ Args:
22
+ path:tina储存记忆,消息和你上传的文件的路径
23
+ LLM:语言模型,目前只支持llama
24
+ tools:你自定义的工具
25
+ toolsLib:你自定义的工具库,python文件路径
26
+ stream:是否实时输出结果
27
+ isSystem:是否使用tina自带的系统工具
28
+ isRAG:是否使用tina自带的RAG工具
29
+ is_tool_call_permission:是否允许工具对系统做出危险操作
30
+ """
31
+ if path is None:
32
+ path = os.path.dirname(__file__)
33
+ if LLM is None:
34
+ raise NotImplementedError("Tina现在还不支持自动加载模型呢,请实例化一个LLM后交给我吧")
35
+ if isRAG is True and embeding_model is None:
36
+ raise ValueError("如果没有向量模型的话,tina没法使用RAG功能哦,使用参数embeding_model指定向量模型路径吧")
37
+ TinaFolderManager.init(path)
38
+ TinaFolderManager.setEmbedingModel(embeding_model)
39
+ self.Tools = Tools(isSystemTools=isSystem, isRAG=isRAG)
40
+ if tools is not None:
41
+ self.Tools.multiregister(tools)
42
+ if toolsLib is not None:
43
+ self.Tools += Tools.loadToolsFromPyFile(toolsLib)
44
+ self.stream = stream
45
+ self.Prompt = Prompt()
46
+ self.agent = Agent(LLM, self.Tools, self.Prompt, is_tool_call_permission)
47
+ self.timeout = timeout
48
+ self.isRAG = isRAG
49
+ self.fileUpload = False
50
+ self.isChat = False
51
+ self.isRemember = False
52
+ self.isExit = False
53
+ self.lock = threading.Lock()
54
+
55
+ def run(self,memory_timeout:int=600):
56
+ self.show_start()
57
+ with self.lock:
58
+ run_thread = threading.Thread(target=self.run_lowerFace)
59
+ remember_thread = threading.Thread(target=self.remembeing,args=(self.timeout,))
60
+ remember_thread.daemon = True
61
+ run_thread.start()
62
+ remember_thread.start()
63
+ if self.isRemember:
64
+ remember_thread.join()
65
+
66
+
67
+
68
+ def run_lowerFace(self):
69
+ while True:
70
+ if self.isRemember is False:
71
+ user_input = input("\n( • ̀ω•́ ) >>>User:\n")
72
+ if user_input == "#exit":
73
+ self.exit()
74
+ break
75
+ elif user_input == "#file":
76
+ self.file()
77
+ elif user_input == "#help":
78
+ self.help()
79
+ elif user_input == "#clear":
80
+ self.clear()
81
+ elif user_input == "#rag":
82
+ if self.isRAG is True:
83
+ self.rag()
84
+ elif user_input.startswith("#rag -isCopy="):
85
+ if self.isRAG is True:
86
+ isCopy = user_input.split("=")[1]
87
+ if isCopy.lower() == "true":
88
+ self.rag(isCopy=True)
89
+ else:
90
+ self.rag()
91
+ else:
92
+ print("你没有开启RAG功能,在实例化的时候添加参数isRAG=True再来试试?")
93
+ else:
94
+
95
+ self.chat(user_input)
96
+ else:
97
+ continue
98
+ def rag(self,isCopy:bool = False):
99
+ foler_path = input("📂 >>>文件夹路径:")
100
+ try:
101
+ docToVec(file_path=foler_path,isCopyToTinaFolder=isCopy)
102
+ print("✅ 文档库建立成功!")
103
+ except Exception as e:
104
+ print(f"❌ 文档库建立失败: {e}")
105
+
106
+ def exit(self):
107
+ print("再见 ヾ( ̄▽ ̄)Bye~Bye~")
108
+ self.isExit = True
109
+ self.remembeing(timeout=0)
110
+
111
+ def remembeing(self,timeout=None):
112
+ while True:
113
+ if self.isChat is False and self.isRemember is False and self.isExit is False:
114
+ if timeout is None:
115
+ time.sleep(self.timeout)
116
+ else:
117
+ time.sleep(timeout)
118
+ with self.lock: # 使用with语句来锁定和释放锁
119
+ self.isRemember = True
120
+ animation_thread = threading.Thread(target=self.show_remember_animation)
121
+ agent_remember_thread = threading.Thread(target=self.agent.remember)
122
+ animation_thread.daemon = True
123
+ animation_thread.start()
124
+ agent_remember_thread.start()
125
+ agent_remember_thread.join()
126
+ self.isRemember = False
127
+ time.sleep(2)
128
+ if self.isRemember is False:
129
+ print(" ", end='\r')
130
+ print("(ゝ∀・)⌒☆ tina记忆完毕!")
131
+ if self.isExit:
132
+ break
133
+ print("\n>>>User:")
134
+
135
+ def file(self):
136
+ self.fileUpload = True
137
+ print(">>>请上传文件(输入文件的URL或路径)")
138
+ file_path = input("📂 >>>File:")
139
+ try:
140
+ self.agent.readFile(file_path)
141
+ print("✅ 文件读取成功")
142
+ except Exception as e:
143
+ print(f"❌ 文件读取失败: {e}")
144
+ self.fileUpload = False
145
+
146
+ def help(self):
147
+ print("📄 帮助文档:")
148
+ print("🛠️ 系统控制台指令:")
149
+ print("#exit: 退出对话,退出时,tina需要一段时间来记忆这次的对话,所以可能会占点时间哦")
150
+ print("#file: 文件上传,tina可以读取本地文件并进行对话,读取过后,用户可以接着对话,文件内容会被包含在上文中")
151
+ print("#help: 查看帮助,就是查看帮助文档啦")
152
+ print("#rag: 建立文档库,tina可以将本地文件夹中的文档转换为向量并建立Faiss索引,这样你就可以使用RAG功能了,试试问她文档里面的有关信息吧")
153
+ print(" 参数:isCopy 是否将文件复制到一个Tina的专用文件夹,默认为True,用法:#rag -isCopy=True 该命令可以复制到Tina的专用文件夹")
154
+ print("#clear: 清屏,当文字太多了的时候就用它吧")
155
+ print("\n⚙️ 参数文档:")
156
+ print("path: tina储存记忆,消息和你上传的文件的路径,可以认为叫做tina的家目录,tina运行产生的各种文件都将保存在这里")
157
+ print("LLM: 语言模型,支持GGUF格式的模型,也支持API形式的模型,那是tina的大脑,没了可就理解不了你说的话了")
158
+ print("tools: 你自定义的工具,python函数形式,可以是任何你想实现的功能,只要你写好了,tina就可以调用它来完成你想做的事情,注意指定python代码的路径哦")
159
+ print("stream: 是否实时输出结果,如果是True,tina会实时输出对话结果,如果是False,tina会在对话结束后输出结果")
160
+ print("timeout: tina记忆的超时时间,默认是600秒,如果用户一直不说话,tina会在这段时间后开始记忆")
161
+ print("embeding_model: 向量模型路径,如果开启RAG功能,tina需要使用向量模型来建立文档库,你需要指定向量模型的路径")
162
+ print("isSystem: 是否使用tina自带的系统工具,如果是True,tina会自动加载系统工具,你可以在这里添加你自己的系统工具")
163
+ print("isRAG: 是否使用tina自带的RAG工具,如果是True,tina会自动加载RAG工具,你可以在这里添加你自己的RAG工具")
164
+
165
+ def clear(self):
166
+ self.show_start()
167
+
168
+ def show_start(self):
169
+ os.system("cls")
170
+ self.show_random_animation()
171
+ print("😊 欢迎使用tina,你可以输入#help来查看帮助")
172
+ print('🤔 退出对话:"#exit"\n📤 文件上传:"#file"\n')
173
+ print('😀 当出现"tina正在记忆信息时..."请不要打断\n')
174
+
175
+ def chat(self, user_input):
176
+ self.isChat = True
177
+ result = self.agent.predict(input_text=user_input,stream=self.stream)
178
+ if self.stream:
179
+ print("\n(・∀・) >>>tina:")
180
+ for chunk in result:
181
+ print(chunk, end="", flush=True)
182
+ else:
183
+ print(result["content"])
184
+ self.isChat = False
185
+
186
+ def show_remember_animation(self):
187
+ messages = [
188
+ '(≧∀≦)ゞ tina正在记忆信息',
189
+ '(≧∀≦)ゞ tina正在记忆信息.',
190
+ '(≧∀≦)ゞ tina正在记忆信息..',
191
+ '(≧∀≦)ゞ tina正在记忆信息...'
192
+ ]
193
+
194
+ while self.isRemember:
195
+ for i in range(len(messages)):
196
+ print(" ", end='\r')
197
+ print(messages[i], end='\r') # 使用end='\r'将光标移回行首
198
+ time.sleep(0.5)
199
+
200
+ def show_random_animation(self):
201
+ animations = [
202
+ '( ̄▽ ̄) ',
203
+ '(´▽`ʃ♡ƪ)" ',
204
+ '(ゝ∀・)ノ ',
205
+ '(ノ^∇^)ノ ',
206
+ '(・∀・) ',
207
+ '(∩^o^)⊃━☆゚.*・。 '
208
+ ]
209
+ animation = random.choice(animations)
210
+ print(animation,"tina by QiQi in 🌟 XIMO\n\n")
211
+
@@ -0,0 +1,3 @@
1
+ def NULLTools():
2
+ print("NULLTools")
3
+ return "你是因为不知道该调用什么函数才会出现这个提示信息的吗?"
@@ -0,0 +1,41 @@
1
+ """
2
+ 编写者:王出日
3
+ 日期:2024,12,1
4
+ 版本?
5
+ 描述:
6
+ 使用QwenEmbeddings库将文本转换为向量,并使用Faiss建立索引。
7
+ 包含:
8
+ QwenDocvec(file_path):将文本文件转换为向量,并建立Faiss索引。
9
+ """
10
+
11
+ import os
12
+ import faiss
13
+ import numpy as np
14
+ from ..core.Embedding.QwenEmbeddings import TextEmbedding
15
+ from ..core.processFiles import fileToTxt
16
+ from ..core.manage import TinaFolderManager
17
+ from ..RAG.textSegments import TextSegments
18
+
19
+ def QwenDocToVec(file_path,dimesion=1536,n=500):
20
+ """
21
+ 将文本文件转换为向量,并建立Faiss索引。
22
+ Args:
23
+ file_path: 文本文件路径
24
+ dimesion: 向量维度
25
+ n: 每个文本分段的最大句子数
26
+ Returns:
27
+ None
28
+ """
29
+ text_segments = TextSegments(file_path)
30
+ text_embedding = TextEmbedding()
31
+ faiss_index = faiss.IndexFlatL2(dimesion)
32
+ faiss_index_file = TinaFolderManager.getFaissIndex()
33
+ text_segments.segments(n)
34
+ for i in range(text_segments.getMaxId()):
35
+ text = text_segments.get(i+1)
36
+ if text == []:
37
+ continue
38
+ vec = text_embedding.embedding(text)
39
+ vec_np = np.array(vec)
40
+ faiss_index.add(vec_np)
41
+ faiss.write_index(faiss_index, faiss_index_file)
tina/tools/__init__.py ADDED
@@ -0,0 +1 @@
1
+ __all__ = ['query','docToVec','systemTools']
@@ -0,0 +1,63 @@
1
+ import os
2
+ import subprocess
3
+ import threading
4
+ from queue import Queue
5
+
6
+
7
+ def writeCode(filename, code):
8
+ path = os.path.join(os.getcwd(), filename)
9
+ with open(filename, 'w') as f:
10
+ f.write(code)
11
+ return path
12
+
13
+ def readCode(filename):
14
+ path = os.path.join(os.getcwd(), filename)
15
+ with open(filename, 'r') as f:
16
+ code = f.read()
17
+ return code
18
+
19
+ def deleteCode(filename):
20
+ path = os.path.join(os.getcwd(), filename)
21
+ os.remove(path)
22
+ return path
23
+
24
+
25
+ def runCode(filename):
26
+ path = os.path.join(os.getcwd(), filename)
27
+
28
+ def _run_script(output_queue):
29
+ try:
30
+ # 直接运行脚本不打开新窗口
31
+ process = subprocess.Popen(
32
+ ['python', path],
33
+ stdout=subprocess.PIPE,
34
+ stderr=subprocess.PIPE,
35
+ text=True,
36
+ encoding='utf-8'
37
+ )
38
+
39
+ # 实时捕获输出
40
+ stdout, stderr = process.communicate()
41
+ output_queue.put({
42
+ 'stdout': stdout,
43
+ 'stderr': stderr,
44
+ 'returncode': process.returncode
45
+ })
46
+
47
+ except Exception as e:
48
+ output_queue.put({'error': str(e)})
49
+
50
+ # 创建通信队列和线程
51
+ output_queue = Queue()
52
+ thread = threading.Thread(target=_run_script, args=(output_queue,))
53
+ thread.start()
54
+
55
+ # 返回队列对象供主程序检查
56
+ return output_queue
57
+ def runCodeNotOpenTerminal(code):
58
+ try:
59
+ result = eval(code)
60
+ return result
61
+ except Exception as e:
62
+ return str(e)
63
+
@@ -0,0 +1,20 @@
1
+ from typing import Union,Generator
2
+ import importlib
3
+ from ..core.processFiles import fileToTxtByExten
4
+
5
+ def readLoogText(path:str = None,URL:str = None) -> Union[Generator,list[str]]:
6
+ if path:
7
+ return fileToTxtByExten(path, isClean=True, isSegments=True, n=100, step=None, is_yield=False)
8
+ elif URL:
9
+ urllib_request = importlib.import_module('urllib.request')
10
+ urlopen = urllib_request.urlopen
11
+ URLError = urllib_request.URLError
12
+ try:
13
+ response = urlopen(URL)
14
+ content = response.read()
15
+ file_path = os.path.join(os.getcwd(),'temp.pdf')
16
+ with open(file_path, 'wb') as f:
17
+ f.write(content)
18
+ return fileToTxtByExten(file_path, isClean=True, isSegments=True, n=100, step=None, is_yield=False)
19
+ except URLError as e:
20
+ print(f"Error: {e}")
tina/tools/search.py ADDED
File without changes
@@ -0,0 +1,51 @@
1
+ import os
2
+ import datetime
3
+ import winreg
4
+ import subprocess
5
+
6
+ def getTime() -> str:
7
+ return datetime.datetime.now().strftime("%Y年-%m月-%d日 %H时%M分%S秒")
8
+
9
+ def shotdownSystem() -> None:
10
+ sure = input("确定关机吗?(Y/n)")
11
+ if sure.lower() == "y":
12
+ os.system("shutdown -s -t 0")
13
+ elif sure.lower() == "n":
14
+ print("取消关机")
15
+ else:
16
+ print("输入错误,取消关机")
17
+
18
+
19
+ def getSystemInfo() -> str:
20
+ return os.popen("systeminfo").read()
21
+
22
+ def getSoftwareList() -> str:
23
+ reg_key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall")
24
+ software_list = []
25
+ try:
26
+ i = 0
27
+ while True:
28
+ # 枚举子键
29
+ sub_key_name = winreg.EnumKey(reg_key, i)
30
+ sub_key = winreg.OpenKey(reg_key, sub_key_name)
31
+
32
+ try:
33
+ # 获取软件名称
34
+ software_name = winreg.QueryValueEx(sub_key, "DisplayName")[0]
35
+ software_list.append(software_name)
36
+ except FileNotFoundError:
37
+ # 如果找不到DisplayName,跳过该软件
38
+ pass
39
+ finally:
40
+ winreg.CloseKey(sub_key)
41
+ i += 1
42
+ except OSError:
43
+ # 当枚举结束时,会抛出OSError
44
+ pass
45
+ finally:
46
+ winreg.CloseKey(reg_key)
47
+ return software_list
48
+
49
+
50
+ def openSoftware(software_name: str) -> bool:
51
+ pass