Spaces:
Sleeping
Sleeping
#Paz Munidal | |
#mi aporte | |
# | |
# Crea una consultor público, al servicio de las personas, sobre las normas formales Chilenas, las que están publicadas oficialmente | |
# en la Biblioteca del Congreso Nacional (www.bcn.cl), quienes a través de sus deberes a la ciudadanía facilitan el accesso a la | |
# información a través de datos en XML, los que luego son alimentados a un modelo LLM (a una A.I.) para que diga cómo lo clasifica en | |
# en arreglos ordenados matematicamente, los que luego matematicamente pueden ser comparados con la pregunta hecha al ingreso de la | |
# consulta y obtener un patron mátématico medible que en el mundo de las ideas, represente la semantica de la pregunta y responder | |
# con la norma que se consulta, en lo que más sentido tenga. | |
# | |
# Esto tiene liciencia GNU GPLv3 <--- software libre y las was que hagai con él también lo deben ser 🤟 (for ever, sin trampas, maldidta rata!!🤗)!!! | |
# @fermaf | |
# Nostr: npub1fermafqdu9ghcmsflq9wdsfwhg3zf93e6n49204ch2ztf98utw6qmhavug | |
# | |
# (de acá en adelante con mis garabatos/comentarios incluidos xd, sin ellos no hubiese hecho la primera iteración!! 🤓 ) | |
# | |
#(https://30days.streamlit.app/) | |
#pip install streamlit | |
i=0 | |
import streamlit as st | |
import xml.etree.ElementTree as ET | |
st.header("Minvu Dijur") | |
st.subheader('Consulta en tu norma favorita 🔎') | |
#option = st.selectbox( | |
# ' ', | |
# ('DS49 (V. y U.) de 2011', 'Ley 21.442 (Ley de copropiedad inmobiliaria)')) | |
######################################################## | |
####################################################### | |
st.sidebar.image('./image/logos/minvu.png') # <--- Este es un caso de uso, para un Consultor con toda la normativa de un organo/servicio del Estado, como el MINVU (en este caso) | |
######################################################## | |
######################################################## | |
norma = st.sidebar.selectbox( | |
"Selecciona una norma", | |
('DS49 (V. y U.) de 2011', 'Ley 21.442 (Ley de copropiedad inmobiliaria)')) | |
#st.write(type(option)) | |
if norma=='DS49 (V. y U.) de 2011': | |
placeholder="¿qué es una entidad patrocinante?" | |
url="https://www.leychile.cl/Consulta/obtxml?opt=7&idNorma=1039424" | |
else: | |
placeholder="¿qué pasa si no se reunieren los quórum para sesionar?" | |
url="https://www.leychile.cl/Consulta/obtxml?opt=7&idNorma=1174663" | |
question = st.text_input("haz una pregunta:",placeholder=placeholder) | |
#st.write("pregunta") | |
#st.write(question) | |
#=st.inp input("ingrese su API key?\n>") | |
openai_api_key = st.text_input("API key de OpenAI :",placeholder="sk-") | |
######### FIN WEB ########### | |
import os | |
os.environ['OPENAI_API_KEY'] = openai_api_key | |
#st.write( os.getenv('OPENAI_API_KEY')) | |
####BAJA NORMA | |
#Para bajar norma de BCN.CL otentiendo el XML | |
#DS49: https://www.leychile.cl/Consulta/obtxml?opt=7&idNorma=1039424 | |
import requests | |
def obtener_contenido_url(url): | |
respuesta = requests.get(url) | |
contenido = respuesta.text | |
return contenido | |
#url = "https://www.leychile.cl/Consulta/obtxml?opt=7&idNorma=1039424" # Reemplazar con la URL deseada, para obtener el XML de la norma | |
#url="https://www.leychile.cl/Consulta/obtxml?opt=7&idNorma=1174663" | |
contenidoXML = obtener_contenido_url(url) #<--contiene el XML de la norma en texto | |
###################### | |
#Normaliza eltexto XML para extraer texto | |
import re | |
def extraer_texto(contenidoXML): | |
# Espacio de nombres del XML | |
namespaces = {'emas': 'http://www.leychile.cl/esquemas'} | |
#print(contenidoXML) | |
# Parsear el archivo XML | |
#arbol = ET.parse(ruta_a_archivo) #tambien se puede pasar la ruta a un archivo /home/hola/ds49.xml | |
#raiz = arbol.getroot() | |
raiz = ET.fromstring(contenidoXML) #forma de "parsear" un XML directo desde string | |
# Crear una lista para almacenar todos los textos | |
textos = [] | |
# Buscar todos los elementos 'texto' en el espacio de nombres correcto | |
for texto in raiz.iter('{http://www.leychile.cl/esquemas}Texto'): | |
texto.text = texto.text.replace("\t", " ") | |
texto.text = re.sub(" +", " ", texto.text) | |
texto.text = texto.text.replace(".\n", ".@") | |
texto.text = texto.text.replace(":\n", ":@") | |
texto.text = texto.text.replace("\n", " ") | |
texto.text = texto.text.replace(".@", ".\n") | |
texto.text = texto.text.replace(":@", ":\n") | |
texto.text = texto.text.strip()+"\n" | |
textos.append(texto.text) | |
return textos | |
############### | |
textos = extraer_texto(contenidoXML) | |
#TEXTO normalizado COMPLETO DE LA NORMA en ascii (sin metadata) | |
texto='\n'.join(textos) | |
#i=i+1 | |
#st.write(i) | |
from langchain.schema import Document | |
documento = [Document(page_content=texto, metadata={"nombre": "norma"})] #<---- del tipo <class 'langchain.schema.document.Document'> | |
#st.write(texto[:200]) | |
from langchain.indexes import VectorstoreIndexCreator | |
#st.write(i) | |
index = VectorstoreIndexCreator().from_documents(documento) | |
#st.write(texto[:100]) | |
############### | |
####MUESRRA Respuesta 1 | |
import time | |
if question: | |
respuesta=index.query(question) | |
st.write("👧 \n ",respuesta) | |
######################################## | |
from langchain.text_splitter import RecursiveCharacterTextSplitter | |
text_splitter = RecursiveCharacterTextSplitter(chunk_size = 500, chunk_overlap = 100) | |
all_splits = text_splitter.split_documents(documento) | |
## | |
from langchain.vectorstores import Chroma | |
from langchain.embeddings import OpenAIEmbeddings | |
vectorstore = Chroma.from_documents(documents=all_splits,embedding=OpenAIEmbeddings()) | |
## | |
if question: | |
docs = vectorstore.similarity_search(question) | |
## | |
#import logging | |
from langchain.chat_models import ChatOpenAI | |
from langchain.retrievers.multi_query import MultiQueryRetriever | |
#logging.basicConfig() | |
#logging.getLogger('langchain.retrievers.multi_query').setLevel(logging.INFO) | |
retriever_from_llm = MultiQueryRetriever.from_llm(retriever=vectorstore.as_retriever(), | |
llm=ChatOpenAI(temperature=0)) | |
if question: | |
unique_docs = retriever_from_llm.get_relevant_documents(query=question) | |
#### | |
from langchain.prompts import ChatPromptTemplate | |
chat = ChatOpenAI(openai_api_key=openai_api_key,temperature=0,max_tokens=600) | |
#customer_style = """alta contenido de modismos chilenos \ | |
#y usando lenguaje con mucho slang | |
#""" | |
#customer_style = """Muy formal y anticuado\ | |
#y usando lenguaje rimbombante. | |
#""" | |
template_string = """En una lista, en la que cada elemento tiene el siguiente formato: \ | |
Document("page_content" y "metadata"), responde usando exclusivamente la información contenida "page_content",\ | |
a la siguiente pregunta: \ | |
pregunta: ```{text}``` \n\n | |
Verifica que la respuesta cumpla con: | |
* Nunca mencionar tus fuentes de informacion, como decir "page_content" o elementos de la lista o documento. | |
* No citar normas ni articulos, pero si es necesesario solo usa la información de "paga_content", señalandor Tipo de norma, año y de quien es y/o el número de articulo. | |
* Tu respuesta puede ser hasta de 600 tokens. | |
Finalmente verifica que la respuesta SIEMPRE responda esta pregunta primordial:\n | |
{pregunta}. \n | |
Si no responde, en no mas de 25 palabras, pide ingresar una nueva preguenta. | |
""" | |
prompt_template = ChatPromptTemplate.from_template(template_string) | |
####MUESRRA Respuesta 2 | |
if question: | |
customer_messages = prompt_template.format_messages( | |
#style=customer_style, | |
pregunta=question, | |
text=unique_docs) | |
respuesta2 = chat(customer_messages) | |
st.divider() | |
st.write("👨\n",respuesta2.content) | |