Spaces:
Runtime error
Runtime error
Salvatore Rossitto
commited on
Commit
·
41dd9cd
1
Parent(s):
4ca6f7b
first_commit
Browse files- .gitignore +7 -0
- LICENSE +21 -0
- RBotReloaded.py +492 -0
- README.md +57 -13
- agent_llama_ui.py +249 -0
- avatar.png +0 -0
- google_free_search.py +74 -0
- requirements.txt +46 -0
- start_agent.bat +22 -0
.gitignore
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
models/*
|
2 |
+
generated_images/*
|
3 |
+
knowledge_base/*
|
4 |
+
__pycache__/*
|
5 |
+
myenv/*
|
6 |
+
.vscode/*
|
7 |
+
.fake
|
LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
MIT License
|
2 |
+
|
3 |
+
Copyright (c) 2023 Salvatore Rossitto
|
4 |
+
|
5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6 |
+
of this software and associated documentation files (the "Software"), to deal
|
7 |
+
in the Software without restriction, including without limitation the rights
|
8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9 |
+
copies of the Software, and to permit persons to whom the Software is
|
10 |
+
furnished to do so, subject to the following conditions:
|
11 |
+
|
12 |
+
The above copyright notice and this permission notice shall be included in all
|
13 |
+
copies or substantial portions of the Software.
|
14 |
+
|
15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21 |
+
SOFTWARE.
|
RBotReloaded.py
ADDED
@@ -0,0 +1,492 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import re
|
3 |
+
from datetime import datetime, timedelta
|
4 |
+
from threading import Thread
|
5 |
+
import asyncio
|
6 |
+
import requests
|
7 |
+
import streamlit as st
|
8 |
+
import json
|
9 |
+
import time
|
10 |
+
from bs4 import BeautifulSoup
|
11 |
+
from PIL import Image
|
12 |
+
import base64
|
13 |
+
import io
|
14 |
+
import google_free_search
|
15 |
+
from langchain.vectorstores import FAISS # For storing embeddings
|
16 |
+
from langchain.chains import RetrievalQA, ConversationalRetrievalChain # Chains for QA
|
17 |
+
from langchain.utilities import TextRequestsWrapper, WikipediaAPIWrapper # Tools
|
18 |
+
from langchain.document_loaders import DirectoryLoader, PyMuPDFLoader, TextLoader, WebBaseLoader # Loaders
|
19 |
+
from langchain.document_loaders.recursive_url_loader import RecursiveUrlLoader # Load URLs
|
20 |
+
from langchain.schema import AIMessage, HumanMessage, get_buffer_string # Chat history
|
21 |
+
from langchain.text_splitter import RecursiveCharacterTextSplitter # Split text
|
22 |
+
from langchain.llms import TextGen, LlamaCpp, CTransformers # Language models
|
23 |
+
from langchain.memory import ConversationBufferMemory # Chat memory
|
24 |
+
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler # Logging
|
25 |
+
from langchain.agents import Tool, load_tools # Tools
|
26 |
+
from langchain.input import get_colored_text # Console colors
|
27 |
+
from langchain.embeddings import (
|
28 |
+
HuggingFaceEmbeddings,
|
29 |
+
LlamaCppEmbeddings,
|
30 |
+
SentenceTransformerEmbeddings,
|
31 |
+
)
|
32 |
+
from diffusers import StableDiffusionPipeline, StableDiffusionImg2ImgPipeline # Image generation
|
33 |
+
from typing import Any, Dict, List
|
34 |
+
import torch
|
35 |
+
from diffusers.pipelines.stable_diffusion.convert_from_ckpt import download_from_original_stable_diffusion_ckpt
|
36 |
+
|
37 |
+
# Config
|
38 |
+
EMBD_CHUNK_SIZE = 512
|
39 |
+
AI_NAME = "Agent Llama"
|
40 |
+
USER_NAME = "Buddy"
|
41 |
+
|
42 |
+
# Helper to load LM
|
43 |
+
def create_llm(model_id="./models/mistral-7b-instruct-v0.1.Q4_K_M.gguf", load_4bit=False, load_8bit=False, ctx_len = 8192, temperature=0.5, top_p=0.95):
|
44 |
+
if (model_id.startswith("http")):
|
45 |
+
print(f"Creating TextGen LLM base_url:{model_id}")
|
46 |
+
return TextGen(model_url=model_id, callbacks=[StreamingStdOutCallbackHandler()])
|
47 |
+
if (os.path.exists(model_id)):
|
48 |
+
try:
|
49 |
+
print(f"Creating LlamaCpp LLM model_id:{model_id}")
|
50 |
+
return LlamaCpp(model_path=model_id, verbose=True, n_batch=521, alpha_value=1,rope_freq_base=10000,compress_pos_emb=ctx_len / 4096, n_ctx=ctx_len, load_in_4bit=load_4bit, load_in_8bit=load_8bit, temperature=temperature,top_p=top_p)
|
51 |
+
except Exception as ex:
|
52 |
+
try:
|
53 |
+
print(f"Creating CTransformers LLM model_id:{model_id}")
|
54 |
+
config = {
|
55 |
+
"context_length": ctx_len,
|
56 |
+
"batch_size":521,
|
57 |
+
"seed":79,
|
58 |
+
"top_p":top_p,
|
59 |
+
"temperature":temperature
|
60 |
+
}
|
61 |
+
return CTransformers(model=model_id, model_type='llama', config=config)
|
62 |
+
|
63 |
+
except Exception as ex:
|
64 |
+
print(f"Load Error {str(ex)}")
|
65 |
+
return None
|
66 |
+
|
67 |
+
# Class to store pages and run queries
|
68 |
+
class StorageRetrievalLLM:
|
69 |
+
|
70 |
+
def __init__(self, stored_pages_folder : str, llm, embeddings):
|
71 |
+
|
72 |
+
# Initialize storage
|
73 |
+
os.makedirs(stored_pages_folder, exist_ok=True)
|
74 |
+
self.stored_pages_folder = stored_pages_folder
|
75 |
+
self.llm = llm
|
76 |
+
self.embeddings = embeddings
|
77 |
+
|
78 |
+
# Try loading existing, else create new
|
79 |
+
try:
|
80 |
+
print(f"Loading StorageRetrievalLLM from disk")
|
81 |
+
self.vectorstore = FAISS.load_local(folder_path=stored_pages_folder, embeddings=embeddings)
|
82 |
+
self.chain = self.create_chain()
|
83 |
+
except:
|
84 |
+
print(f"Initializing a new instance of StorageRetrievalLLM")
|
85 |
+
|
86 |
+
print(f"Loading PDF")
|
87 |
+
self.vectorstore = None
|
88 |
+
self.chain = None
|
89 |
+
|
90 |
+
# Load pages
|
91 |
+
loader = DirectoryLoader(stored_pages_folder, glob="**/*.pdf", loader_cls=PyMuPDFLoader)
|
92 |
+
documents = loader.load()
|
93 |
+
|
94 |
+
# Split into chunks
|
95 |
+
text_splitter = RecursiveCharacterTextSplitter(chunk_size=EMBD_CHUNK_SIZE, chunk_overlap=100)
|
96 |
+
documents = text_splitter.split_documents(documents)
|
97 |
+
|
98 |
+
if len(documents) > 0:
|
99 |
+
# Create index
|
100 |
+
print(f"Creating FAISS index FROM {len(documents)} documents")
|
101 |
+
self.vectorstore = FAISS.from_documents(documents, embeddings)
|
102 |
+
self.vectorstore.save_local(folder_path=stored_pages_folder)
|
103 |
+
else:
|
104 |
+
print(f"Initializing with empty FAISS index")
|
105 |
+
self.vectorstore = FAISS.from_texts(["Knowledge Base: Use the learning tools (learnOnline, wikipedia, etc...) to increase tour knownledge."], embeddings)
|
106 |
+
|
107 |
+
if llm:
|
108 |
+
# Create chain
|
109 |
+
self.chain = self.create_chain()
|
110 |
+
|
111 |
+
# Helper to create retrieval chain
|
112 |
+
def create_chain(self, vectorstore = None, llm = None, embeddings = None):
|
113 |
+
if vectorstore is None:
|
114 |
+
vectorstore = self.vectorstore
|
115 |
+
if llm is None:
|
116 |
+
llm = self.llm
|
117 |
+
if embeddings is None:
|
118 |
+
embeddings = self.embeddings
|
119 |
+
|
120 |
+
print(f"Creating Retriever llm chain")
|
121 |
+
retriever = vectorstore.as_retriever(search_kwargs={"k": 5})
|
122 |
+
chain = ConversationalRetrievalChain.from_llm(llm=llm, retriever=retriever, return_source_documents=False)
|
123 |
+
return chain
|
124 |
+
|
125 |
+
# Add URL
|
126 |
+
def addUrlToMemory(self, url : str, summarize = True):
|
127 |
+
|
128 |
+
loader = RecursiveUrlLoader(url=url, max_depth=2, extractor=lambda x: BeautifulSoup(x, "html.parser").text)
|
129 |
+
docs = loader.load()
|
130 |
+
|
131 |
+
# Split
|
132 |
+
splitter = RecursiveCharacterTextSplitter()
|
133 |
+
documents = splitter.split_documents(docs)
|
134 |
+
|
135 |
+
# Add
|
136 |
+
self.vectorstore.add_documents(documents)
|
137 |
+
|
138 |
+
# Update chain
|
139 |
+
self.chain = self.create_chain()
|
140 |
+
|
141 |
+
# Summarize
|
142 |
+
if summarize:
|
143 |
+
return self.query(query=f"return a short summary about the website {url}, try to not exceed 3500 tokens")
|
144 |
+
else:
|
145 |
+
return f"URL {url} Parsed and collected into memory vectorstore..."
|
146 |
+
|
147 |
+
# Add document
|
148 |
+
def addDocumentToMemory(self, doc : str, summarize = True):
|
149 |
+
|
150 |
+
# Load file
|
151 |
+
file_path = doc if os.path.exists(doc) else os.path.join("data", doc)
|
152 |
+
loader = DirectoryLoader(file_path, glob="**/*.pdf", loader_cls=PyMuPDFLoader)
|
153 |
+
documents = loader.load()
|
154 |
+
|
155 |
+
# Split and add
|
156 |
+
splitter = RecursiveCharacterTextSplitter()
|
157 |
+
documents = splitter.split_documents(documents)
|
158 |
+
self.vectorstore.add_documents(documents)
|
159 |
+
|
160 |
+
# Update chain
|
161 |
+
self.chain = self.create_chain()
|
162 |
+
|
163 |
+
# Summarize
|
164 |
+
if summarize:
|
165 |
+
return self.query(query=f"return a short summary about the doc {file_path}, try to not exceed 3500 tokens")
|
166 |
+
else:
|
167 |
+
return f"File {file_path} Parsed and collected into memory vectorstore..."
|
168 |
+
|
169 |
+
# Add text file
|
170 |
+
def addTextFileToMemory(self, file_path : str, summarize = True):
|
171 |
+
|
172 |
+
# Load file
|
173 |
+
loader = TextLoader(path=file_path, loader_cls=PyMuPDFLoader)
|
174 |
+
documents = loader.load()
|
175 |
+
|
176 |
+
# Split and add
|
177 |
+
splitter = RecursiveCharacterTextSplitter()
|
178 |
+
documents = splitter.split_documents(documents)
|
179 |
+
self.vectorstore.add_documents(documents)
|
180 |
+
|
181 |
+
# Update chain
|
182 |
+
self.chain = self.create_chain()
|
183 |
+
|
184 |
+
# Summarize
|
185 |
+
if summarize:
|
186 |
+
return self.query(query=f"return a short summary about the file {file_path}, try to not exceed 3500 tokens")
|
187 |
+
else:
|
188 |
+
return f"File {file_path} Parsed and collected into memory vectorstore..."
|
189 |
+
|
190 |
+
# Add text
|
191 |
+
def addTextToMemory(self, text : str, summarize = True):
|
192 |
+
|
193 |
+
# Add text
|
194 |
+
self.vectorstore.add_texts([text])
|
195 |
+
|
196 |
+
# Update chain
|
197 |
+
self.chain = self.create_chain()
|
198 |
+
|
199 |
+
# Summarize
|
200 |
+
if summarize:
|
201 |
+
return self.query(query=f"return a short summary about the text {text[:10]}, try to not exceed 3500 tokens")
|
202 |
+
else:
|
203 |
+
return "Text Parsed and collected into memory vectorstore..."
|
204 |
+
|
205 |
+
# Run query
|
206 |
+
def query(self, query: str, chat_history = []):
|
207 |
+
res = self.chain({"question" : query, "chat_history" : chat_history})
|
208 |
+
return res['answer']
|
209 |
+
|
210 |
+
# Class for agent
|
211 |
+
class RBotAgent:
|
212 |
+
|
213 |
+
def __init__(self, llm, tools, max_iterations=3, observations_callback=None):
|
214 |
+
self.llm = llm
|
215 |
+
self.tools = tools
|
216 |
+
self.max_iterations=max_iterations
|
217 |
+
self.observations_callback = observations_callback
|
218 |
+
|
219 |
+
# Get tools prompt
|
220 |
+
def tools_prompt(self):
|
221 |
+
return "\n".join([ f"Action: {tool.name}(query_params) - Description: {tool.description}" for tool in self.tools])
|
222 |
+
|
223 |
+
# Main handler
|
224 |
+
def __call__(self, params):
|
225 |
+
|
226 |
+
input = params["input"]
|
227 |
+
chat_history = params["chat_history"]
|
228 |
+
formatted_history = get_buffer_string(chat_history, human_prefix="USER")
|
229 |
+
|
230 |
+
prompt = f"""
|
231 |
+
EXAMPLE 1:
|
232 |
+
USER: Find me a recipe for chocolate chip cookies.
|
233 |
+
AI: SearchAndReply("chocolate chip cookies recipe", 5) #params query, max_results=5
|
234 |
+
|
235 |
+
EXAMPLE 2:
|
236 |
+
USER: Show me pictures of cute puppies.
|
237 |
+
AI: ImageGenerator("cute puppies", 512, 512) #params: prompt, width=512, height=512, denoise_strength=0.75, guidance_scale=7.5, negative_prompt = "")
|
238 |
+
EXAMPLE 3:
|
239 |
+
USER: Explain the concept of blockchain.
|
240 |
+
AI: KnowledgeBaseQuery("Explain blockchain") #params query
|
241 |
+
|
242 |
+
EXAMPLE 4:
|
243 |
+
USER: Find me recent news about cryptocurrency.
|
244 |
+
AI: SearchAndReply("recent cryptocurrency news") #params query, max_results=5
|
245 |
+
|
246 |
+
EXAMPLE 5:
|
247 |
+
USER: Can you calculate the factorial of 5?
|
248 |
+
AI: Calculator("factorial(5)") #params query
|
249 |
+
|
250 |
+
###REAL CONVERSATION:\n
|
251 |
+
SYS:Today is {str(datetime.now().date())},
|
252 |
+
You are {AI_NAME} a smart and helpful AI assistant with access to external tools and knowledge.
|
253 |
+
Please reply to the user with a truth and useful response, if you do not know the answer or you are not sure or you need more recent informations, delegate the task replying with ActionName(action_input) with the most appropriate of the available actions (you call them like functions).\nCurrent Conversation History:
|
254 |
+
|
255 |
+
###AVAILABLE TOOL ACTIONS
|
256 |
+
{self.tools_prompt()}
|
257 |
+
|
258 |
+
{formatted_history}
|
259 |
+
USER: {input}
|
260 |
+
AI:
|
261 |
+
"""
|
262 |
+
observations = []
|
263 |
+
|
264 |
+
# Try calling tools
|
265 |
+
tool_names = [tool.name.lower() for tool in self.tools]
|
266 |
+
for i in range(self.max_iterations):
|
267 |
+
|
268 |
+
print(f"iteration {i+1} - sending prompt:\n" + prompt)
|
269 |
+
for i in [1,2,3]:
|
270 |
+
output = str(self.llm(prompt,stop=["USER:","AI:","SYS:","[INST]","[/INST]"])).strip()
|
271 |
+
if output: break
|
272 |
+
|
273 |
+
|
274 |
+
return_role = output.split(":")[0]
|
275 |
+
return_message = output[len(return_role)+1:].split("[INST]")[0].split("[/INST]")[0].split("User")[0].split("USER")[0].strip()
|
276 |
+
|
277 |
+
# Try to parse action request
|
278 |
+
action_name = None
|
279 |
+
action_input = None
|
280 |
+
matches = re.findall(r"(\w+)\((.+?)\)", return_message)
|
281 |
+
for match in matches:
|
282 |
+
if len(match) > 1 and match[0] and match[1]:
|
283 |
+
if match[0].strip().lower() in tool_names:
|
284 |
+
action_name = match[0].strip().lower()
|
285 |
+
action_input = match[1].strip().replace("query_params", "").strip().replace("()","")
|
286 |
+
break
|
287 |
+
|
288 |
+
# Try unformatted
|
289 |
+
if not action_name or not action_input:
|
290 |
+
lines = output.split("\n")
|
291 |
+
|
292 |
+
|
293 |
+
for line in lines:
|
294 |
+
for tool in tool_names:
|
295 |
+
if f"{tool}:" in line.lower() or f"{tool}(" in line.lower():
|
296 |
+
action_name = tool
|
297 |
+
action_input = line[line.lower().find(tool)+len(tool):].strip().replace("query_params", "").strip().replace("()","")
|
298 |
+
print(f"Matched unformatted action request. {action_name}:{action_input} from line: {line}")
|
299 |
+
break
|
300 |
+
|
301 |
+
# Call tool if found
|
302 |
+
if action_name and action_input:
|
303 |
+
for tool in self.tools:
|
304 |
+
if tool.name.lower() in action_name:
|
305 |
+
print(f"Calling action:{tool.name} with input:{action_input}")
|
306 |
+
observations.append(f"Calling action:{tool.name} with input:{action_input}")
|
307 |
+
|
308 |
+
params_list = action_input.split(",")
|
309 |
+
try:
|
310 |
+
try:
|
311 |
+
res = tool.func(*params_list)
|
312 |
+
except:
|
313 |
+
res = tool.func(action_input)
|
314 |
+
except Exception as ex:
|
315 |
+
res = f"{action_name} execution error: {str(ex)}"
|
316 |
+
|
317 |
+
print(f"Action Output: {res}")
|
318 |
+
observations.append(f"Action Output: {res}")
|
319 |
+
prompt = prompt + f"Action: {tool.name}({action_input})\nSYS:{res}\nAI:"
|
320 |
+
else:
|
321 |
+
final_response = "\n*Reasoning: ".join(observations) + f"\n{output}" if len(observations) > 0 else f"\n{output}"
|
322 |
+
print(f"Final Anser: {final_response}")
|
323 |
+
return { "output": final_response }
|
324 |
+
|
325 |
+
return { "output": "Max Iterations reached. Last Output:\n" + output}
|
326 |
+
|
327 |
+
# Main agent class
|
328 |
+
class SmartAgent:
|
329 |
+
|
330 |
+
def __init__(self, model_id: str, conversation_model = "", emb_model="all-MiniLM-L6-v2", load_in_4bit=False, load_in_8bit=True, ctx_len=16384, temp=0.1, top_p=0.95, max_iterations=3, observations_callback = None):
|
331 |
+
|
332 |
+
self.chat_history = []
|
333 |
+
self.max_iterations = max_iterations
|
334 |
+
self.model = model_id
|
335 |
+
self.current_message = ""
|
336 |
+
|
337 |
+
# Load LM
|
338 |
+
self.llm = create_llm(model_id, load_4bit=load_in_4bit, load_8bit=load_in_8bit, ctx_len=ctx_len, temperature=temp, top_p=top_p)
|
339 |
+
|
340 |
+
# Load embeddings
|
341 |
+
self.embeddings = SentenceTransformerEmbeddings(model_name=emb_model)
|
342 |
+
|
343 |
+
# Initialize memory
|
344 |
+
self.memory_chain = StorageRetrievalLLM(stored_pages_folder="./knowledge_base", llm=self.llm, embeddings=self.embeddings)
|
345 |
+
|
346 |
+
#TOOL REQUEST
|
347 |
+
self.requests_tool = TextRequestsWrapper()
|
348 |
+
|
349 |
+
#Wikipedia
|
350 |
+
self.wikipedia_tool = WikipediaAPIWrapper()
|
351 |
+
|
352 |
+
self.image2image_gen_pipe = None
|
353 |
+
self.text2image_gen_pipe = None
|
354 |
+
|
355 |
+
# Create agent
|
356 |
+
self.smartAgent = self.create_smart_agent()
|
357 |
+
|
358 |
+
print("Smart Agent Initialized")
|
359 |
+
|
360 |
+
def reset_context(self):
|
361 |
+
self.chat_history.clear()
|
362 |
+
|
363 |
+
# Create image
|
364 |
+
def createImage(self, prompt, width=512, height=512, denoise_strength=0.75, guidance_scale=7.5, model_id = 'dreamshaper_8.safetensors'):
|
365 |
+
try:
|
366 |
+
init_image = None
|
367 |
+
if (os.path.exists("./image_gen_guide.jpg")):
|
368 |
+
init_image = Image.open("./image_gen_guide.jpg")
|
369 |
+
|
370 |
+
images = []
|
371 |
+
if init_image is None:
|
372 |
+
if self.text2image_gen_pipe is None:
|
373 |
+
if torch.cuda.is_available():
|
374 |
+
print(f"Loading Stable model {model_id} into GPU")
|
375 |
+
self.text2image_gen_pipe = StableDiffusionPipeline.from_single_file("./models/" + model_id, torch_dtype=torch.float16, verbose=True, use_safetensors=True)
|
376 |
+
self.text2image_gen_pipe = self.text2image_gen_pipe.to("cuda")
|
377 |
+
else:
|
378 |
+
print(f"Loading Stable model {model_id} into CPU")
|
379 |
+
self.text2image_gen_pipe = StableDiffusionPipeline.from_single_file("./models/" + model_id, torch_dtype=torch.float32, verbose=True, use_safetensors=True)
|
380 |
+
self.text2image_gen_pipe = self.text2image_gen_pipe.to("cpu")
|
381 |
+
print("generating image from promt...")
|
382 |
+
images = self.text2image_gen_pipe(prompt, width=width, height=height).images
|
383 |
+
else:
|
384 |
+
if self.image2image_gen_pipe is None:
|
385 |
+
if torch.cuda.is_available():
|
386 |
+
print(f"Loading Stable model {model_id} into GPU")
|
387 |
+
self.image2image_gen_pipe = StableDiffusionImg2ImgPipeline.from_single_file("./models/" + model_id, torch_dtype=torch.float16, verbose=True, use_safetensors=True)
|
388 |
+
self.image2image_gen_pipe = self.image2image_gen_pipe.to("cuda")
|
389 |
+
else:
|
390 |
+
print(f"Loading Stable model {model_id} into CPU")
|
391 |
+
self.image2image_gen_pipe = StableDiffusionImg2ImgPipeline.from_single_file("./models/" + model_id, torch_dtype=torch.float32, verbose=True, use_safetensors=True)
|
392 |
+
self.image2image_gen_pipe = self.image2image_gen_pipe.to("cpu")
|
393 |
+
print("generating image from promt+image...")
|
394 |
+
init_image = init_image.convert("RGB")
|
395 |
+
images = self.image2image_gen_pipe(prompt, image=init_image, width=width, height=height, strength=denoise_strength, guidance_scale=guidance_scale).images
|
396 |
+
|
397 |
+
paths = []
|
398 |
+
for image in (images if images is not None else []):
|
399 |
+
# Create a filename based on the current date and time
|
400 |
+
filename = f'image_{datetime.now().strftime("%Y%m%d%H%M%S")}{(len(paths)+1)}.jpg'
|
401 |
+
# Save the image to the specified path
|
402 |
+
file_path = f"./generated_images/{filename}"
|
403 |
+
image.save(file_path)
|
404 |
+
paths.append(file_path)
|
405 |
+
return f"Generated images from prompt \"{prompt}\" saved to files: {', '.join(paths)}"
|
406 |
+
except Exception as e:
|
407 |
+
print(f"error in createImageLocal: {e}")
|
408 |
+
return "Unable to generate file"
|
409 |
+
|
410 |
+
def load_and_split_documents(self, url, max_depth=2):
|
411 |
+
loader = RecursiveUrlLoader(url, max_depth=max_depth, extractor=lambda x: BeautifulSoup(x, "html.parser").text)
|
412 |
+
docs = loader.load()
|
413 |
+
splitter = RecursiveCharacterTextSplitter()
|
414 |
+
return splitter.split_documents(docs)
|
415 |
+
|
416 |
+
def search_and_reply(self, query, max_results=5):
|
417 |
+
vectorstore = None
|
418 |
+
sources = ""
|
419 |
+
res_cnt = 0
|
420 |
+
results = google_free_search.gsearch(query=query)
|
421 |
+
#urls = [ur['link'].strip() for ur in results]
|
422 |
+
urls = []
|
423 |
+
for result in results:
|
424 |
+
link = result['link']
|
425 |
+
title = result['title']
|
426 |
+
if (link.startswith("http://") or link.startswith("https://")):
|
427 |
+
res_cnt = res_cnt +1
|
428 |
+
if res_cnt > max_results: break
|
429 |
+
print(f"- Found Valid Link {title} : {link}")
|
430 |
+
sources += f"{title}, "
|
431 |
+
urls.append(link)
|
432 |
+
else:
|
433 |
+
print(f"ERROR! Invalid link: {link} for result: {title}")
|
434 |
+
|
435 |
+
if len(urls) > 0:
|
436 |
+
import concurrent.futures
|
437 |
+
print(f"Loading {len(urls)} urls into a vectore store")
|
438 |
+
|
439 |
+
with concurrent.futures.ThreadPoolExecutor() as executor:
|
440 |
+
future_results = [executor.submit(self.load_and_split_documents, url) for url in urls]
|
441 |
+
|
442 |
+
documents = []
|
443 |
+
for future in concurrent.futures.as_completed(future_results):
|
444 |
+
documents.extend(future.result())
|
445 |
+
|
446 |
+
if len(documents) > 0:
|
447 |
+
vectorstore = FAISS.from_documents(documents, self.embeddings)
|
448 |
+
|
449 |
+
if vectorstore is not None:
|
450 |
+
retriever = vectorstore.as_retriever(search_kwargs={"k": 5})
|
451 |
+
chain = RetrievalQA.from_chain_type(llm=self.llm, chain_type="stuff", retriever=retriever)
|
452 |
+
response = chain.run(self.current_message + " " + datetime.now().strftime("%Y/%m/%d"))
|
453 |
+
ret_message = response #['answer']
|
454 |
+
return ret_message
|
455 |
+
else:
|
456 |
+
return f"Unable to acquire results from web search results:{len(results)} - valids:{res_cnt}"
|
457 |
+
|
458 |
+
# Main handler
|
459 |
+
def agent_generate_response(self, user_message):
|
460 |
+
|
461 |
+
start_time = time.time()
|
462 |
+
|
463 |
+
self.current_message = user_message
|
464 |
+
# Get response
|
465 |
+
message_response = self.smartAgent({"input" : user_message, "chat_history" : self.chat_history})
|
466 |
+
|
467 |
+
end_time = time.time()
|
468 |
+
elapsed_time = end_time - start_time
|
469 |
+
|
470 |
+
# Format response
|
471 |
+
response = message_response['output'] + f" ({round(elapsed_time,2)}s)"
|
472 |
+
self.chat_history.append(HumanMessage(content=user_message))
|
473 |
+
self.chat_history.append(AIMessage(content=message_response['output']))
|
474 |
+
|
475 |
+
return response
|
476 |
+
|
477 |
+
# Create agent
|
478 |
+
def create_smart_agent(self):
|
479 |
+
|
480 |
+
# Tools
|
481 |
+
tools = [
|
482 |
+
Tool(name="SearchAndReply", func=self.search_and_reply, description="Search web and reply"),
|
483 |
+
Tool(name="Wikipedia", func=self.wikipedia_tool.run, description="Query Wikipedia"),
|
484 |
+
Tool(name="ImageGenerator", func=self.createImage, description="Generate images"),
|
485 |
+
Tool(name="KnowledgeBaseQuery", func=self.memory_chain.query, description="Query knowledge base"),
|
486 |
+
]
|
487 |
+
tools.extend(load_tools(["llm-math"], llm=self.llm))
|
488 |
+
|
489 |
+
# test_reply = self.llm(f"Hello {AI_NAME}")
|
490 |
+
# print(f"Test reply to Hello: {test_reply}")
|
491 |
+
|
492 |
+
return RBotAgent(llm=self.llm, tools=tools, max_iterations=self.max_iterations)
|
README.md
CHANGED
@@ -1,13 +1,57 @@
|
|
1 |
-
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Agent Llama007B: A Conversational AI Assistant
|
2 |
+
|
3 |
+

|
4 |
+
|
5 |
+
## Overview
|
6 |
+
|
7 |
+
AgentLlama007B is a powerful Conversational AI Assistant designed for natural language interactions and task automation. It leverages state-of-the-art language models and offers seamless integration with external tools and knowledge sources. Whether you need to engage in casual conversations or perform specific tasks, AgentLlama007B has you covered.
|
8 |
+
|
9 |
+
## Key Features
|
10 |
+
|
11 |
+
- **Natural Language Conversations**: Engage in human-like conversations powered by local language models.
|
12 |
+
- **Tool Integration**: Execute various tools, including image generation, web search, Wikipedia queries, and more, all within the conversation.
|
13 |
+
- **Persistent Memory**: Contextual knowledge is stored in a vector database, providing continuity and enhancing the conversational experience.
|
14 |
+
- **Modular Architecture**: Easily extend AgentLlama007B with additional skills and tools to suit your specific needs.
|
15 |
+
|
16 |
+
## Getting Started
|
17 |
+
|
18 |
+
To start using AgentLlama007B, follow these simple steps:
|
19 |
+
|
20 |
+
Clone the repo and create a folder "models", than download the Models you need from hugging face and put them in the models folder.
|
21 |
+
I use mistral-7b-instruct-v0.1.Q4_K_M.gguf for chat/instructions and dreamshaper_8 for images generation (:P you'll need dreamshaper_8.json and dreamshaper_8.safetensors)
|
22 |
+
|
23 |
+
1. Install the required dependencies by running `pip install -r requirements.txt`.
|
24 |
+
|
25 |
+
2. Run the main Streamlit app:
|
26 |
+
|
27 |
+
```bash
|
28 |
+
streamlit run agent_llama_ui.py
|
29 |
+
```
|
30 |
+
|
31 |
+
3. Alternatively, you can integrate the agent into your Python code:
|
32 |
+
|
33 |
+
```python
|
34 |
+
from agent_llama import SmartAgent
|
35 |
+
|
36 |
+
agent = SmartAgent()
|
37 |
+
|
38 |
+
while True:
|
39 |
+
user_input = input("You: ")
|
40 |
+
response = agent.agent_generate_response(user_input)
|
41 |
+
print("Bot:", response)
|
42 |
+
```
|
43 |
+
|
44 |
+
For more details on customization, model configuration, and tool parameters, refer to the code documentation.
|
45 |
+
|
46 |
+
## Implementation
|
47 |
+
|
48 |
+
AgentLlama007B's core logic is encapsulated in the `RBotAgent` class, which manages the conversational flow and tool integration. The knowledge base tool, `StorageRetrievalLLM`, uses persistent memory with a FAISS index of document embeddings. Various tools are provided, each encapsulating specific skills such as image generation and web search. The modular architecture allows easy replacement of components like the language model.
|
49 |
+
|
50 |
+
## Credits
|
51 |
+
|
52 |
+
This project was created by Salvatore Rossitto as a passion project and a learning endeavor. Contributions from the community are welcome and encouraged.
|
53 |
+
|
54 |
+
## License
|
55 |
+
|
56 |
+
AgentLlama007B is an open-source project released under the MIT license. You are free to use, modify, and distribute it as per the terms of the license.
|
57 |
+
|
agent_llama_ui.py
ADDED
@@ -0,0 +1,249 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
from streamlit_chat import message
|
3 |
+
import os
|
4 |
+
import io
|
5 |
+
from dotenv import load_dotenv
|
6 |
+
import requests
|
7 |
+
import glob
|
8 |
+
import json
|
9 |
+
import shutil
|
10 |
+
from RBotReloaded import SmartAgent
|
11 |
+
import time
|
12 |
+
from PIL import Image
|
13 |
+
from langchain.schema import AIMessage, HumanMessage
|
14 |
+
|
15 |
+
load_dotenv()
|
16 |
+
|
17 |
+
|
18 |
+
default_model = ""
|
19 |
+
default_context = 8192
|
20 |
+
default_load_type = "Auto"
|
21 |
+
default_iterations = 2
|
22 |
+
default_temperature = 0.5
|
23 |
+
default_topp = 0.95
|
24 |
+
|
25 |
+
@st.cache_resource
|
26 |
+
def agent(model, temperature, top_p, context_length, load_8bit, load_4bit, max_iterations):
|
27 |
+
ag = SmartAgent(f"./models/{model}" if os.path.exists(f"./models/{model}") else model, temp=temperature, top_p=top_p, load_in_4bit=load_4bit, load_in_8bit=load_8bit, ctx_len=context_length, max_iterations=max_iterations) if model else None
|
28 |
+
st.session_state["temperature_executive"] = temperature
|
29 |
+
st.session_state["max_iterations_executive"] = max_iterations
|
30 |
+
st.session_state["model_executive"] = model
|
31 |
+
st.session_state["context_length_executive"] = context_length
|
32 |
+
st.session_state["load_options_executive"] = "Load 4-bit" if load_8bit else "Load 4-bit" if load_4bit else "Auto"
|
33 |
+
st.session_state["top_p_executive"] = top_p
|
34 |
+
|
35 |
+
return ag
|
36 |
+
|
37 |
+
def get_models():
|
38 |
+
supported_extensions = ["bin","pth","gguf"]
|
39 |
+
models_directory = "./models" # Replace with the actual path
|
40 |
+
# Use os.listdir to get a list of filenames in the directory
|
41 |
+
models = os.listdir(models_directory)
|
42 |
+
# Filter out any subdirectories, if any
|
43 |
+
models = [model for model in models if (model.lower().split(".")[-1] in supported_extensions) and os.path.isfile(os.path.join(models_directory, model))]
|
44 |
+
if len(models) == 0:
|
45 |
+
from huggingface_hub import hf_hub_download
|
46 |
+
hf_hub_download(repo_id="TheBloke/Mistral-7B-Instruct-v0.1-GGUF", filename="mistral-7b-instruct-v0.1.Q4_K_M.gguf", local_dir=models_directory)
|
47 |
+
hf_hub_download(repo_id="digiplay/DreamShaper_8", filename="dreamshaper_8.safetensors", local_dir=models_directory)
|
48 |
+
|
49 |
+
models.append("http://localhost:5000")
|
50 |
+
return models
|
51 |
+
|
52 |
+
def current_agent():
|
53 |
+
model = st.session_state.get("model", default_model)
|
54 |
+
temperature = st.session_state.get("temperature", default_temperature)
|
55 |
+
max_iterations = st.session_state.get("max_iterations", default_iterations)
|
56 |
+
context_length = st.session_state.get("context_length", default_context)
|
57 |
+
load_options = st.session_state.get("load_options", default_load_type)
|
58 |
+
top_p = st.session_state.get("top_p", default_topp)
|
59 |
+
|
60 |
+
model = st.session_state.get("model_executive", model)
|
61 |
+
temperature = st.session_state.get("temperature_executive", temperature)
|
62 |
+
max_iterations = st.session_state.get("max_iterations_executive", max_iterations)
|
63 |
+
context_length = st.session_state.get("context_length_executive", context_length)
|
64 |
+
load_options = st.session_state.get("load_options_executive", load_options)
|
65 |
+
top_p = st.session_state.get("top_p_executive", top_p)
|
66 |
+
|
67 |
+
return agent(model, temperature, top_p, context_length, load_options=="Load 8-bit", load_options=="Load 4-bit", max_iterations)
|
68 |
+
|
69 |
+
def history():
|
70 |
+
return [] if current_agent() is None else current_agent().chat_history
|
71 |
+
|
72 |
+
#@st.cache_data
|
73 |
+
def generate_text(input):
|
74 |
+
start_time = time.time()
|
75 |
+
output = "Error: Model not Loaded!" if current_agent() is None else current_agent().agent_generate_response(input)
|
76 |
+
end_time = time.time()
|
77 |
+
elapsed_time = end_time - start_time
|
78 |
+
|
79 |
+
print(f"\n----------------------")
|
80 |
+
print(f"Agent Reply: {output} - Input: {input}")
|
81 |
+
print(f"Elapsed Time: {elapsed_time} seconds")
|
82 |
+
print(f"Agent Reply: {output}")
|
83 |
+
print(f"\n----------------------")
|
84 |
+
return output + f" ({round(elapsed_time,2)}s)"
|
85 |
+
|
86 |
+
|
87 |
+
def get_generated_files():
|
88 |
+
# Specify the directory path where the generated images are stored
|
89 |
+
directory = "./generated_images"
|
90 |
+
|
91 |
+
# Get the list of files in the directory
|
92 |
+
files = glob.glob(f"{directory}/*.jpg") # Modify the file extension as per your generated image format
|
93 |
+
|
94 |
+
# Return the list of file paths
|
95 |
+
return files
|
96 |
+
|
97 |
+
# Function to list files in the "./knowledge_base/" folder
|
98 |
+
def list_files_in_knowledge_base_folder():
|
99 |
+
knowledge_base_folder = "./knowledge_base/"
|
100 |
+
files = os.listdir(knowledge_base_folder)
|
101 |
+
return [file for file in files if os.path.isfile(os.path.join(knowledge_base_folder, file))]
|
102 |
+
|
103 |
+
# Function to add a file to the "./knowledge_base/" folder
|
104 |
+
def add_file_to_knowledge_base(file):
|
105 |
+
knowledge_base_folder = "./knowledge_base/"
|
106 |
+
final_path = os.path.join(knowledge_base_folder, file.name)
|
107 |
+
|
108 |
+
with open(final_path, "wb") as f:
|
109 |
+
f.write(file.read())
|
110 |
+
|
111 |
+
if current_agent() is None:
|
112 |
+
st.error("Model Not Loaded!")
|
113 |
+
else:
|
114 |
+
current_agent().memory_chain.addDocumentToMemory(os.path.join(knowledge_base_folder, file.name))
|
115 |
+
|
116 |
+
# Function to add a file to the "./knowledge_base/" folder
|
117 |
+
def set_image_gen_guide(file):
|
118 |
+
bytes_data = io.BytesIO(file.read())
|
119 |
+
image = Image.open(bytes_data)
|
120 |
+
image = image.convert("RGB")
|
121 |
+
image.save("./image_gen_guide.jpg")
|
122 |
+
|
123 |
+
def unset_image_gen_guide():
|
124 |
+
if os.path.exists("./image_gen_guide.jpg"):
|
125 |
+
os.remove("./image_gen_guide.jpg")
|
126 |
+
|
127 |
+
def get_index_size():
|
128 |
+
index_file_path = "./knowledge_base/index.faiss" # Replace with the actual path to your index file
|
129 |
+
if os.path.exists(index_file_path):
|
130 |
+
index_size = os.path.getsize(index_file_path)
|
131 |
+
return index_size / 1024
|
132 |
+
else:
|
133 |
+
print(f"{index_file_path} does not exist or is not accessible.")
|
134 |
+
return 0
|
135 |
+
|
136 |
+
# @cl.langchain_factory(use_async=True)
|
137 |
+
# def factory():
|
138 |
+
# return current_agent().smartAgent
|
139 |
+
|
140 |
+
def render_simple_chat():
|
141 |
+
models = get_models()
|
142 |
+
models.append("")
|
143 |
+
|
144 |
+
model = st.session_state.get("model", default_model)
|
145 |
+
temperature = st.session_state.get("temperature", default_temperature)
|
146 |
+
max_iterations = st.session_state.get("max_iterations", default_iterations)
|
147 |
+
context_length = st.session_state.get("context_length", default_context)
|
148 |
+
load_options = st.session_state.get("load_options", default_load_type)
|
149 |
+
top_p = st.session_state.get("top_p", default_topp)
|
150 |
+
|
151 |
+
with st.sidebar:
|
152 |
+
st.image("./avatar.png")
|
153 |
+
st.sidebar.title("LLM Options")
|
154 |
+
max_iterations = st.sidebar.slider("Max Iterations", min_value=1, max_value=10, step=1, key="max_iterations")
|
155 |
+
model = st.selectbox(label="Model", options=models, key="model")
|
156 |
+
if (not model.startswith("http")):
|
157 |
+
temperature = st.sidebar.slider("Temperature", min_value=0.1, max_value=1.0, step=0.1, key="temperature")
|
158 |
+
top_p = st.sidebar.slider("top_p", min_value=0.1, max_value=1.0, step=0.1, key="top_p")
|
159 |
+
context_length = st.sidebar.slider("Context Length", min_value=1024, max_value=131072, step=1024, key="context_length")
|
160 |
+
# Load Options
|
161 |
+
load_options = st.sidebar.radio("Load Options", ["Auto", "Load 4-bit", "Load 8-bit"], key="load_options")
|
162 |
+
|
163 |
+
if (st.sidebar.button("Apply Changes to Model")):
|
164 |
+
st.session_state["temperature_executive"] = temperature
|
165 |
+
st.session_state["max_iterations_executive"] = max_iterations
|
166 |
+
st.session_state["model_executive"] = model
|
167 |
+
st.session_state["context_length_executive"] = context_length
|
168 |
+
st.session_state["load_options_executive"] = load_options
|
169 |
+
st.session_state["top_p_executive"] = top_p
|
170 |
+
#st.experimental_rerun()
|
171 |
+
|
172 |
+
if st.sidebar.button("Reset Chat Context", disabled=not (current_agent() is not None and len(current_agent().chat_history) > 0)) and current_agent() is not None:
|
173 |
+
current_agent().reset_context()
|
174 |
+
|
175 |
+
st.sidebar.write("-----")
|
176 |
+
|
177 |
+
st.sidebar.title("Documents Context")
|
178 |
+
st.sidebar.subheader(f"Current Memory Size {round(get_index_size() / 1024,2)}MB")
|
179 |
+
|
180 |
+
uploaded_file = st.sidebar.file_uploader("Drag and Drop a File to ./knowledge_base/", type=["txt", "pdf", "docx"])
|
181 |
+
|
182 |
+
if st.sidebar.button("Reset Long Term Memory", disabled=not (current_agent() is not None and get_index_size() > 0)) and current_agent() is not None:
|
183 |
+
current_agent().reset_knowledge()
|
184 |
+
|
185 |
+
st.sidebar.write("-----")
|
186 |
+
|
187 |
+
st.sidebar.title("Images Generation")
|
188 |
+
|
189 |
+
if os.path.exists("./image_gen_guide.jpg"):
|
190 |
+
st.sidebar.image("./image_gen_guide.jpg")
|
191 |
+
if st.sidebar.button("Remove Image Generation Guidance"):
|
192 |
+
unset_image_gen_guide()
|
193 |
+
st.experimental_rerun()
|
194 |
+
else:
|
195 |
+
image_gen_guide = st.sidebar.file_uploader("Drag and Drop an image for the image generation", type=["jpg", "png"])
|
196 |
+
if image_gen_guide:
|
197 |
+
set_image_gen_guide(image_gen_guide)
|
198 |
+
st.sidebar.success(f"File '{image_gen_guide.name}' set as image generation guidance.")
|
199 |
+
|
200 |
+
if uploaded_file:
|
201 |
+
add_file_to_knowledge_base(uploaded_file)
|
202 |
+
st.sidebar.success(f"File '{uploaded_file.name}' added to Knowledge Base.")
|
203 |
+
|
204 |
+
with st.sidebar:
|
205 |
+
#GENERATED FILES
|
206 |
+
generated_files = get_generated_files()
|
207 |
+
st.sidebar.subheader("Generated Files")
|
208 |
+
for file_path in generated_files:
|
209 |
+
st.write("---")
|
210 |
+
st.write(file_path.split("/")[-1].split("\\")[-1])
|
211 |
+
st.image(file_path)
|
212 |
+
|
213 |
+
i = 0
|
214 |
+
for m in history():
|
215 |
+
i = i +1
|
216 |
+
gen = str(m.content)
|
217 |
+
#saved to files: ./generated_images/image_202310091819331.jpg
|
218 |
+
if str(gen).endswith(".jpg") and os.path.exists(gen.split(" ")[-1]):
|
219 |
+
st.image(gen.split(" ")[-1])
|
220 |
+
|
221 |
+
message(gen, is_user=m.type.lower() == "human", key=str(i))
|
222 |
+
|
223 |
+
user_input = st.chat_input("Prompt", key="input_text")
|
224 |
+
if user_input:
|
225 |
+
message(user_input, is_user=True, key=str(i+1))
|
226 |
+
res = generate_text(user_input)
|
227 |
+
message(res, is_user=False, key=str(i+2))
|
228 |
+
|
229 |
+
|
230 |
+
##### BEGIN MAIN #####
|
231 |
+
if 'generated' not in st.session_state:
|
232 |
+
st.session_state['generated'] = []
|
233 |
+
|
234 |
+
if 'past' not in st.session_state:
|
235 |
+
st.session_state['past'] = []
|
236 |
+
|
237 |
+
if 'model' not in st.session_state:
|
238 |
+
st.session_state['model'] = default_model
|
239 |
+
st.session_state['temperature'] = default_temperature
|
240 |
+
st.session_state['max_iterations'] = default_iterations
|
241 |
+
st.session_state['context_length'] = default_context
|
242 |
+
st.session_state['load_options'] = default_load_type
|
243 |
+
st.session_state['top_p'] = default_topp
|
244 |
+
|
245 |
+
st.set_page_config(page_title="Agent Llama", page_icon="🤖", layout="wide")
|
246 |
+
|
247 |
+
st.title("Agent Llama")
|
248 |
+
|
249 |
+
render_simple_chat()
|
avatar.png
ADDED
![]() |
google_free_search.py
ADDED
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from bs4 import BeautifulSoup
|
2 |
+
import requests, json, lxml
|
3 |
+
|
4 |
+
def gsearch(query : str, max: int = 10, country = "us", lang = "en"):
|
5 |
+
# https://docs.python-requests.org/en/master/user/quickstart/#passing-parameters-in-urls
|
6 |
+
params = {
|
7 |
+
"q": query.replace("\"",""), # query example
|
8 |
+
"hl": lang, # language
|
9 |
+
"gl": country, # country of the search, UK -> United Kingdom
|
10 |
+
"start": 0, # number page by default up to 0
|
11 |
+
"num": max # parameter defines the maximum number of results to return.
|
12 |
+
}
|
13 |
+
|
14 |
+
# https://docs.python-requests.org/en/master/user/quickstart/#custom-headers
|
15 |
+
headers = {
|
16 |
+
"User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
|
17 |
+
}
|
18 |
+
|
19 |
+
page_limit = 10
|
20 |
+
page_num = 0
|
21 |
+
data = []
|
22 |
+
|
23 |
+
while True:
|
24 |
+
page_num += 1
|
25 |
+
html = requests.get("https://www.google.com/search", params=params, headers=headers, timeout=30)
|
26 |
+
soup = BeautifulSoup(html.text, 'lxml')
|
27 |
+
|
28 |
+
for result in soup.select('.tF2Cxc'):
|
29 |
+
title = result.select_one('.DKV0Md').text
|
30 |
+
link = result.select_one('.yuRUbf a')['href']
|
31 |
+
|
32 |
+
# sometimes there's no description and we need to handle this exception
|
33 |
+
try:
|
34 |
+
snippet = result.select_one('#rso .lyLwlc').text
|
35 |
+
except:
|
36 |
+
snippet = None
|
37 |
+
|
38 |
+
if (link.startswith("http")):
|
39 |
+
data.append({
|
40 |
+
'title': title,
|
41 |
+
'link': link,
|
42 |
+
'snippet': snippet
|
43 |
+
})
|
44 |
+
|
45 |
+
if page_num == page_limit:
|
46 |
+
break
|
47 |
+
if soup.select_one(".d6cvqb a[id=pnnext]"):
|
48 |
+
params["start"] += 10
|
49 |
+
else:
|
50 |
+
break
|
51 |
+
|
52 |
+
return data
|
53 |
+
|
54 |
+
|
55 |
+
# -------------
|
56 |
+
# '''
|
57 |
+
# [
|
58 |
+
# {
|
59 |
+
# "title": "Tesla: Electric Cars, Solar & Clean Energy",
|
60 |
+
# "link": "https://www.tesla.com/",
|
61 |
+
# "snippet": "Tesla is accelerating the world's transition to sustainable energy with electric cars, solar and integrated renewable energy solutions for homes and ..."
|
62 |
+
# },
|
63 |
+
# {
|
64 |
+
# "title": "Tesla, Inc. - Wikipedia",
|
65 |
+
# "link": "https://en.wikipedia.org/wiki/Tesla,_Inc.",
|
66 |
+
# "snippet": "Tesla, Inc. is an American electric vehicle and clean energy company based in Palo Alto, California, United States. Tesla designs and manufactures electric ..."
|
67 |
+
# },
|
68 |
+
# {
|
69 |
+
# "title": "Nikola Tesla - Wikipedia",
|
70 |
+
# "link": "https://en.wikipedia.org/wiki/Nikola_Tesla",
|
71 |
+
# "snippet": "Nikola Tesla was a Serbian-American inventor, electrical engineer, mechanical engineer, and futurist best known for his contributions to the design of the ..."
|
72 |
+
# }
|
73 |
+
# ]
|
74 |
+
# '''
|
requirements.txt
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
accelerate
|
2 |
+
aiohttp
|
3 |
+
anyio
|
4 |
+
bitsandbytes
|
5 |
+
bs4
|
6 |
+
diffusers
|
7 |
+
transformers
|
8 |
+
faiss-cpu
|
9 |
+
fastapi
|
10 |
+
git-python
|
11 |
+
google-search-results
|
12 |
+
httptools
|
13 |
+
huggingface
|
14 |
+
huggingface-hub
|
15 |
+
json5
|
16 |
+
langchain
|
17 |
+
numexpr
|
18 |
+
llama_cpp_python
|
19 |
+
psutil
|
20 |
+
PyMuPDF
|
21 |
+
safetensors
|
22 |
+
selenium
|
23 |
+
sentence-transformers
|
24 |
+
sentencepiece
|
25 |
+
streamlit_chat
|
26 |
+
streamlit>=0.86.0
|
27 |
+
textblob
|
28 |
+
undetected-chromedriver
|
29 |
+
urllib3
|
30 |
+
virtualenv
|
31 |
+
wikipedia
|
32 |
+
datetime
|
33 |
+
asyncio
|
34 |
+
requests
|
35 |
+
bs4
|
36 |
+
Pillow
|
37 |
+
langchain
|
38 |
+
googletrans
|
39 |
+
torch
|
40 |
+
torchaudio
|
41 |
+
#torchaudio==2.0.1+cu117
|
42 |
+
torchvision
|
43 |
+
python-dotenv
|
44 |
+
lxml
|
45 |
+
ctransformers
|
46 |
+
omegaconf
|
start_agent.bat
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
@echo off
|
2 |
+
|
3 |
+
rem Define the name of your virtual environment
|
4 |
+
set ENV_NAME=myenv
|
5 |
+
|
6 |
+
rem Check if the virtual environment folder exists
|
7 |
+
if not exist %ENV_NAME% (
|
8 |
+
rem Create a new virtual environment
|
9 |
+
python -m venv %ENV_NAME%
|
10 |
+
)
|
11 |
+
|
12 |
+
rem Activate the virtual environment
|
13 |
+
call %ENV_NAME%\Scripts\activate
|
14 |
+
|
15 |
+
rem Install the required packages from requirements.txt
|
16 |
+
python -m pip install -r requirements.txt
|
17 |
+
|
18 |
+
rem Run your Streamlit application
|
19 |
+
python -m streamlit run agent_llama_ui.py
|
20 |
+
|
21 |
+
rem Deactivate the virtual environment
|
22 |
+
deactivate
|