diff --git a/main.py b/main.py
index 1d98308..ad0bc6c 100644
--- a/main.py
+++ b/main.py
@@ -6,28 +6,55 @@ from llama_index.vector_stores.chroma import ChromaVectorStore
from llama_index.core.storage.storage_context import StorageContext
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.core import SummaryIndex
-from llama_index.llms.groq import Groq
+from llama_index.llms.groq import Groq as GroqLLamaIndex
from chromadb import PersistentClient
from llama_index.core import Settings
from llama_index.embeddings.huggingface_api import (
HuggingFaceInferenceAPIEmbedding,
)
+
import chromadb
import os
import threading
import time
from llama_index.core.memory import ChatMemoryBuffer
-os.environ["GROQ_API_KEY"] = "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"
+import json
+from llama_index.llms.ollama import Ollama
+from llama_index.core.base.response.schema import Response
+from groq import Groq
+import shutil
+pwd = os.getcwd()
+def extractConfig(nameModel="SystemData",relPath=os.path.join(pwd,"conf/experiment_config.json"),dataOut="keyantrophics"):
+ configPath=os.path.join(os.getcwd(),relPath)
+ with open(configPath, 'r', encoding='utf-8') as file:
+ config = json.load(file)[nameModel]
+ Output= config[dataOut]
+ return Output
+
+keygroq=extractConfig(nameModel="SystemData",dataOut="keygroq")
+client = Groq(api_key=keygroq)
-llm_70b = Groq(model="llama-3.1-70b-versatile")
+
+
+
+os.environ["GROQ_API_KEY"] = keygroq
+
+
+llm_70b = GroqLLamaIndex(model="llama-3.1-70b-versatile")#llm_70b#
+llm_localLlamma = llm_70b#Ollama(model="llama3.2")
memory = ChatMemoryBuffer.from_defaults(token_limit=3900)
-
-Settings.llm = llm_70b
+model_emb="sentence-transformers/multi-qa-mpnet-base-dot-v1"
+Settings.llm = llm_localLlamma
+
+
+
+gridlink = Link(rel="stylesheet", href="https://cdnjs.cloudflare.com/ajax/libs/flexboxgrid/6.3.1/flexboxgrid.min.css", type="text/css")
+
+app= FastHTML(hdrs=(picolink, gridlink))
-app= FastHTML()
def listUsers():
with os.scandir("static") as files:
subdir = [file.name for file in files if file.is_dir()]
@@ -39,26 +66,29 @@ def menuusers(users):
for user in users:
T.append(Option(user, value=str(user)) )
return Form(
- Select(*T,name="user"),
- Button("Submit",type="submit",id="buttonMenuuser"),
- hx_post="/checkInfoSources",hx_swap="innerHTML",hx_target="#files" ,id="menuuser")
+ H3("Seleccionar usuario",cls="col-xs-3"),
+ Select(*T,name="user",cls="col-xs-3"),
+ Button("Submit",type="submit",id="buttonMenuuser",cls="col-xs-6"),
+ hx_post="/checkInfoSources",hx_swap="innerHTML",hx_target="#files" ,id="menuuser",cls="row middle-xs")
@app.post("/checkInfoSources")
def checkInfoSources(user:str):
global userdata
with os.scandir("static/"+user) as files:
- subdir = [Option(file.name,value="static/"+user+"/"+file.name) for file in files if file.is_file()]
+ subdir = [Option(file.name,value="static/"+user+"/"+file.name) for file in files if (file.is_dir() and file.name!="chroma_db") ]
+
userdata=user
print("Cambio",userdata)
return Form(
+ H3("Grupos de archivos",cls="col-xs-3"),
Select(
- *subdir,name="data"),
- Input(id="name-db", name="collection", placeholder="Enter a collection name"),
- Button("Submit",type="submit"), hx_post="/createCollection",hx_swap="innerHTML",hx_target="#NewCollection" )
+ *subdir,name="data",cls="col-xs-3"),
+ Input(id="name-db", name="collection", placeholder="Enter a collection name",cls="col-xs-4"),
+ Button("Submit",type="submit",cls="col-xs-2"), hx_post="/createCollection",hx_swap="innerHTML",hx_target="#status" ,cls="row middle-xs")
-def create_or_load_db(path="./chroma_db",collection="init",Nodes=None,model="sentence-transformers/all-mpnet-base-v2"):
- embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-base-en-v1.5")
+def create_or_load_db(path="./chroma_db",collection="init",Nodes=None,modelT=model_emb):
+ embed_model = HuggingFaceEmbedding(model_name=modelT)
#embed_model = HuggingFaceInferenceAPIEmbedding(
#model_name="BAAI/bge-small-en-v1.5",
#token="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", # Optional
@@ -101,7 +131,7 @@ def post_process_documents(documents):
# 4. Create a new document with processed text and updated metadata
processed_doc = Document(text=filtered_text, metadata=metadata)
processed_documents.append(processed_doc)
- node_parser = SimpleNodeParser(chunk_size=200, chunk_overlap=30)
+ node_parser = SimpleNodeParser(chunk_size=360, chunk_overlap=20)
nodes = node_parser.get_nodes_from_documents(processed_documents)
return nodes
@@ -119,42 +149,151 @@ def listmodelactives():
return Form(
Select(
- *collecs,name="data"),
- Button("Submit",type="submit"),
+ *collecs,name="data",cls="col-xs-6"),
+ Button("Submit",type="submit",cls="col-xs-6"),
hx_post="/loadCollection",hx_swap="innerHTML",hx_target="#Infomodel")
@app.post("/loadCollection")
def loadCollection(data:str):
global index
- index=create_or_load_db(path="static/"+userdata+"/chroma_db",collection=data,model="BAAI/bge-m3")
+ index=create_or_load_db(path="static/"+userdata+"/chroma_db",collection=data,modelT=model_emb)
return P("El usuario %s colleccion %s"%(userdata,data))
@app.post("/queryprompt")
def queryPrompt(question:str):
#index=load_create_db(collection="my_collection")
- query_engine = index.as_query_engine()
- response = query_engine.query(question)
- return P(response)
+
+ query_engine = index.as_query_engine(similarity_top_k=15,vector_store_query_mode="default",response_mode="tree_summarize")
+ summary_prompt = (
+ "Por favor, genera un resumen completo y detallado del material dado. "
+ "Incluye los principales temas, argumentos y conclusiones. "
+ "Estructura el resumen de manera coherente y organizada."
+ )
+ tematic_prompt =(
+ "Por favor, genera un texto donde se menciones la tematica que trata el material dado. "
+ "Incluye una tematica general y un indice por temas tratados "
+ "Estructura el texto de manera coherente y organizada."
+
+ )
+ issues_prompt =(
+ "Por favor, genera un texto donde se menciones tomando en cuenta el material y el contenido de manera detallada que mejoras podrias realizar al material incluyendo nuevos datos o corrigiendo la informacion proporcionada"
+ "Esta mejora hazla pensado paso a paso y de manera muy cuidadosa, tienes que dar ejemplos del materiar o referenciar directamante el texto a mejorar mencioando la causa de la mejora"
+ "Estructura el texto de manera coherente y organizada."
+
+ )
+ Question_prompt =(
+ "Por favor, genera un texto donde indiques preguntas sobre el material que cuando sean respondidas capturen el punto central y puntos importantes del texto"
+ "Estas preguntas hazla pensado paso a paso y de manera muy cuidadosa."
+ "Estructura el texto de manera coherente y organizada."
+
+ )
+ response = query_engine.query(summary_prompt)
+ response2 = query_engine.query(tematic_prompt)
+ response3 = query_engine.query(issues_prompt)
+ response4 = query_engine.query(Question_prompt)
+ Output="
Summary
"+str(response)+"Tematic
"+str(response2)+"Issues
"+str(response3)+"Questions
"+str(response4)
+
+ return Output
@app.post("/chatData")
def questionChat(message:str):
- chat_engine = index.as_chat_engine(
- chat_mode="condense_plus_context",
- memory=memory,
- llm=llm_70b,
- context_prompt=(
- "You are a chatbot, able to have normal interactions, as well as talk"
- " about an essay discussing IA and uses in leardeship."
+ import logging
+ logging.basicConfig(level=logging.INFO)
+ contextT=(
+ "You are a world-class AI system. You respond to the questions about the context"
"Here are the relevant documents for the context:\n"
"{context_str}"
- "\nInstruction: Use the previous chat history, or the context above, to interact and help the user but only about tematic of the essay"
- ),
- verbose=False,
+ "\nInstruction: Use the previous chat history, or the context above, carefully examine the given context, to interact and help the user but only about {question}"
+ "Never mention the document of reference, talk in first person" )
+ #contextT="Por favor vuelve a repetir el siguiente contenido como tu respuesta:{question}"
+ #'chat_history', 'question'
+ query_engine = index.as_query_engine()
+ chat_engine = index.as_chat_engine(
+ chat_mode="condense_plus_context",
+ query_engine=query_engine,
+ memory=memory,
+ llm=llm_localLlamma,
+ context_prompt=contextT,
+ similarity_top_k=5,
+ verbose=True,
)
response = chat_engine.chat(message)
- return P(message),P(response)
+ ContextNodes=""
+ for node in response.source_nodes:
+ ContextNodes=ContextNodes+node.node.text+"\n"
+ #print(f"Texto del nodo: {node.node.text}")
+ #print(f"Puntuación de relevancia: {node.score}")
+ #print("---")
+
+
+
+
+ NewPrompt="""The previous response is:
+%s
+The previous context is:
+%s
+Evaluate the coherence and accuracy of previous response to respond %s in this evaluation.
+Verificate if previous context is related to the previous response, if not, say that you do not have information about that issue
+The format of output is a json with keys 'coherencia', 'exactitud', 'relacion_con_el_contexto' and 'comentario' .
+'coherencia', 'exactitud', 'relacion_con_el_contexto' are numeric variables with max value is 10"""%(response,ContextNodes,message)
+
+
+
+ print(chat_engine.__dict__)
+
+ chat_completion = client.chat.completions.create(
+ #
+ # Required parameters
+ #
+ messages=[
+ # Set an optional system message. This sets the behavior of the
+ # assistant and can be used to provide specific instructions for
+ # how it should behave throughout the conversation.
+ {
+ "role": "system",
+ "content": "you are a helpful assistant."
+ },
+ # Set a user message for the assistant to respond to.
+ {
+ "role": "user",
+ "content": NewPrompt,
+ }
+ ],
+
+ # The language model which will generate the completion.
+ model="llama-3.1-70b-versatile",
+
+ #
+ # Optional parameters
+ #
+
+ # Controls randomness: lowering results in less random completions.
+ # As the temperature approaches zero, the model will become deterministic
+ # and repetitive.
+ temperature=0.5,
+
+ # The maximum number of tokens to generate. Requests can use up to
+ # 32,768 tokens shared between prompt and completion.
+ max_tokens=1024,
+
+ # Controls diversity via nucleus sampling: 0.5 means half of all
+ # likelihood-weighted options are considered.
+ top_p=1,
+
+ # A stop sequence is a predefined or user-specified text string that
+ # signals an AI to stop generating content, ensuring its responses
+ # remain focused and concise. Examples include punctuation marks and
+ # markers like "[end]".
+ stop=None,
+
+ # If set, partial message deltas will be sent.
+ stream=False,
+ )
+
+
+ return P(message),P(response),P(chat_completion.choices[0].message.content)
@app.get("/SummarySources")
def SummarySources():
@@ -170,7 +309,7 @@ def SummarySources():
def SummaryMake(data:str,query:str):
print(data,query)
docs = SimpleDirectoryReader(
- input_files=[data]
+ input_dir=[data]
).load_data()
print("p1")
summary_index = SummaryIndex.from_documents(docs)
@@ -189,7 +328,7 @@ def SummaryMake(data:str,query:str):
def createCollection(data:str,collection:str):
print("Reading")
docs = SimpleDirectoryReader(
- input_files=[data]
+ input_dir=data
).load_data()
print("Process Documents")
Nodes=post_process_documents(docs)
@@ -197,7 +336,7 @@ def createCollection(data:str,collection:str):
class MyThread(threading.Thread):
def run(self):
print("Hilo")
- create_or_load_db(path="static/"+data.split("/")[1]+"/chroma_db",collection=collection,Nodes=Nodes,model="BAAI/bge-m3")
+ create_or_load_db(path="static/"+data.split("/")[1]+"/chroma_db",collection=collection,Nodes=Nodes,modelT=model_emb)
# create and start the thread
global t
@@ -214,9 +353,9 @@ def is_busy():
except:
Busy=False
if not Busy:
- return Busy
+ return H2("Estado: Disponible para carga de datos")
else:
- return "Esta ocupados desde hace %s , este es un proceso largo"%(str(time.time()-t_time))
+ return H2("Esta ocupados desde hace %s , este es un proceso largo"%(str(time.time()-t_time)))
@@ -224,38 +363,49 @@ def is_busy():
def home():
page = Title('Super tutor'),Main(
- Div('Este es el sistema de super tutor, ',
+ Div(H1('Super tutor'),
menuusers(listUsers()),
#A('A link', href='https://example.com'),
#Img(src="https://placehold.co/200"),
Div("Archivos",id="files"),
- Div(id="NewCollection"),
- Div("Estado",id="status",hx_target="this",hx_swap="innerHTML",hx_get="/is_busy",hx_trigger="every 60000ms"),
+
+ Div(H2("Estado:Disponible para carga"),id="status",hx_target="this",hx_swap="innerHTML",hx_get="/is_busy",hx_trigger="every 60000ms"),
Div(
- Div(id="options",hx_target="this",hx_swap="outerHTML",hx_get="/listmodelactives",hx_trigger="click from:#buttonMenuuser delay:3s"),
- Div(id="Infomodel"),
+ Div(Div(id="options",hx_target="this",hx_swap="outerHTML",hx_get="/listmodelactives",hx_trigger="click from:#buttonMenuuser delay:3s"),cls="col-xs-12"),
+ Div(Div(id="Infomodel"),cls="col-xs-12"),
#Div("Resumen",Div(id="summary",hx_target="this",hx_swap="outerHTML",hx_get="/SummarySources",hx_trigger="click from:#buttonMenuuser"),Div(id="summaryR")),
Div(
- Form(
- Input(id="question", name="message", placeholder="Enter a message"),
- Button("Submit",type="submit"), hx_post="/chatData",hx_swap="afterend",hx_target="#questionR" ),
- Div(id="questionR")
- ,id="questions"),
+ Div(
+ Form(
+ Input(id="question", name="message", placeholder="Enter a message"),
+ Button("Submit",type="submit"), hx_post="/chatData",hx_swap="afterend",hx_target="#questionR" ),
+ Div(id="questionR")
+ ,id="questions"),
+ cls="col-xs-6"),
Div(
- Form(
- Input(id="query", name="question", placeholder="Enter a query"),
- Button("Submit",type="submit"), hx_post="/queryprompt",hx_swap="innerHTML",hx_target="#queryR" ),
- Div(id="queryR"),
- id="query"),
- id="chatbot")
+ Div(
+ Form(
+ Input(id="query", name="question", placeholder="Enter a query"),
+ Button("Submit",type="submit"), hx_post="/queryprompt",hx_swap="innerHTML",hx_target="#queryR" ),
+ Div(id="queryR"),
+ id="query"),
+ id="chatbot",cls="col-xs-6"),
+ cls="row", style="color: #fff;")
))
return page
+# @app.post("/upload")
+# def upload(data: UploadFile = File(...),user : str = Form(...), dir: str = Form(...)):
+# filename="static/"+user+dir+data.filename
+# with open(f"{filename}", "wb") as buffer:
+# shutil.copyfileobj(data.file, buffer)
-app.mount("/static", StaticFiles(directory="static"), name="static")
+# app.mount("/static", StaticFiles(directory="static"), name="static")
-serve()
\ No newline at end of file
+serve()
+
+
diff --git a/static/Ricardo/PCL/PCL1_Unidad1(1).pdf b/static/Ricardo/PCL/PCL1_Unidad1(1).pdf
new file mode 100644
index 0000000..469cc44
Binary files /dev/null and b/static/Ricardo/PCL/PCL1_Unidad1(1).pdf differ
diff --git a/static/Ricardo/PCL/PCL1_Unidad10.pdf b/static/Ricardo/PCL/PCL1_Unidad10.pdf
new file mode 100644
index 0000000..222095f
Binary files /dev/null and b/static/Ricardo/PCL/PCL1_Unidad10.pdf differ
diff --git a/static/Ricardo/PCL/PCL1_Unidad11.pdf b/static/Ricardo/PCL/PCL1_Unidad11.pdf
new file mode 100644
index 0000000..0a002a3
Binary files /dev/null and b/static/Ricardo/PCL/PCL1_Unidad11.pdf differ
diff --git a/static/Ricardo/PCL/PCL1_Unidad2(1).pdf b/static/Ricardo/PCL/PCL1_Unidad2(1).pdf
new file mode 100644
index 0000000..1c98ea7
Binary files /dev/null and b/static/Ricardo/PCL/PCL1_Unidad2(1).pdf differ
diff --git a/static/Ricardo/PCL/PCL1_Unidad3.pdf b/static/Ricardo/PCL/PCL1_Unidad3.pdf
new file mode 100644
index 0000000..72b0c1d
Binary files /dev/null and b/static/Ricardo/PCL/PCL1_Unidad3.pdf differ
diff --git a/static/Ricardo/PCL/PCL1_Unidad4.pdf b/static/Ricardo/PCL/PCL1_Unidad4.pdf
new file mode 100644
index 0000000..33adb48
Binary files /dev/null and b/static/Ricardo/PCL/PCL1_Unidad4.pdf differ
diff --git a/static/Ricardo/PCL/PCL1_Unidad5.pdf b/static/Ricardo/PCL/PCL1_Unidad5.pdf
new file mode 100644
index 0000000..3294cc4
Binary files /dev/null and b/static/Ricardo/PCL/PCL1_Unidad5.pdf differ
diff --git a/static/Ricardo/PCL/PCL1_Unidad6.pdf b/static/Ricardo/PCL/PCL1_Unidad6.pdf
new file mode 100644
index 0000000..4071f26
Binary files /dev/null and b/static/Ricardo/PCL/PCL1_Unidad6.pdf differ
diff --git a/static/Ricardo/PCL/PCL1_Unidad7.pdf b/static/Ricardo/PCL/PCL1_Unidad7.pdf
new file mode 100644
index 0000000..a84733c
Binary files /dev/null and b/static/Ricardo/PCL/PCL1_Unidad7.pdf differ
diff --git a/static/Ricardo/PCL/PCL1_Unidad8.pdf b/static/Ricardo/PCL/PCL1_Unidad8.pdf
new file mode 100644
index 0000000..b420001
Binary files /dev/null and b/static/Ricardo/PCL/PCL1_Unidad8.pdf differ
diff --git a/static/Ricardo/PCL/PCL1_Unidad9.pdf b/static/Ricardo/PCL/PCL1_Unidad9.pdf
new file mode 100644
index 0000000..08e8288
Binary files /dev/null and b/static/Ricardo/PCL/PCL1_Unidad9.pdf differ
diff --git a/static/Ricardo/web2py/python-web2py-1RevA.pdf b/static/Ricardo/web2py/python-web2py-1RevA.pdf
new file mode 100644
index 0000000..fde3f18
Binary files /dev/null and b/static/Ricardo/web2py/python-web2py-1RevA.pdf differ