update
This commit is contained in:
parent
be65aa977b
commit
4cf171c8a2
14
Dockerfile
14
Dockerfile
|
|
@ -8,21 +8,19 @@ WORKDIR /app
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
build-essential \
|
build-essential \
|
||||||
curl \
|
curl \
|
||||||
libpq-dev \
|
|
||||||
protobuf-compiler \
|
protobuf-compiler \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
RUN pip install --no-cache-dir --upgrade pip
|
RUN pip install --no-cache-dir --upgrade pip
|
||||||
|
|
||||||
RUN pip install --no-cache-dir \
|
RUN pip install --no-cache-dir \
|
||||||
langchain==0.1.0 \
|
langchain==0.1.0 \
|
||||||
langfuse>=2.0.0 \
|
langchain-community==0.0.10 \
|
||||||
langgraph \
|
|
||||||
langchain-openai \
|
|
||||||
langchain-elasticsearch \
|
langchain-elasticsearch \
|
||||||
grpcio \
|
grpcio \
|
||||||
grpcio-tools \
|
grpcio-tools \
|
||||||
psycopg2-binary \
|
grpcio-reflection \
|
||||||
pydantic
|
pydantic
|
||||||
|
|
||||||
COPY ./protos ./protos
|
COPY ./protos ./protos
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
@ -34,5 +32,5 @@ RUN python -m grpc_tools.protoc \
|
||||||
./protos/brunix.proto
|
./protos/brunix.proto
|
||||||
|
|
||||||
EXPOSE 50051
|
EXPOSE 50051
|
||||||
#CMD ["tail", "-f", "/dev/null"]
|
|
||||||
CMD ["python", "src/server.py"]
|
CMD ["python", "src/server.py"]
|
||||||
34
README.md
34
README.md
|
|
@ -14,35 +14,21 @@ The following diagram illustrates the interaction between the AVAP technology, t
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
graph TD
|
graph TD
|
||||||
subgraph Client_Layer [External Interface]
|
subgraph Local_Dev [Laptop Ivar/Rafael]
|
||||||
Client[External Services / UI]
|
BE[Brunix Assistance Engine]
|
||||||
|
KT[Kubectl Tunnel]
|
||||||
end
|
end
|
||||||
|
|
||||||
subgraph Engine_Layer
|
subgraph Vultr_K8s_Cluster [Production - Vultr Cloud]
|
||||||
BE[Brunix Assistance Engine]
|
EDB[(Elasticsearch Vector DB - HDD)]
|
||||||
LG[LangGraph Logic]
|
|
||||||
LC[LangChain Framework]
|
|
||||||
end
|
|
||||||
|
|
||||||
subgraph Intelligence_Layer
|
|
||||||
LLM[Fine-tuned Model / OpenAI or other]
|
|
||||||
Prompt[Prompt Engineering]
|
|
||||||
end
|
|
||||||
|
|
||||||
subgraph Data_Observability_Layer [System Support]
|
|
||||||
EDB[(Elasticsearch Vector DB)]
|
|
||||||
LF[Langfuse Observability]
|
|
||||||
PG[(Postgres - System Data)]
|
PG[(Postgres - System Data)]
|
||||||
|
LF[Langfuse UI]
|
||||||
end
|
end
|
||||||
|
|
||||||
Client -- gRPC:50052 --> BE
|
BE -- localhost:9200/5432 --> KT
|
||||||
BE --> LG
|
KT -- Secure Tunnel --> EDB
|
||||||
LG --> LC
|
KT -- Secure Tunnel --> PG
|
||||||
LC --> LLM
|
BE -- Public IP --> LF
|
||||||
LLM --> Prompt
|
|
||||||
LC -- Semantic Search --> EDB
|
|
||||||
LC -- Tracing/Metrics --> LF
|
|
||||||
LF -- Persistence --> PG
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
|
||||||
|
|
@ -7,57 +7,15 @@ services:
|
||||||
ports:
|
ports:
|
||||||
- "50052:50051"
|
- "50052:50051"
|
||||||
environment:
|
environment:
|
||||||
- ELASTICSEARCH_URL=http://elasticsearch:9200
|
- ELASTICSEARCH_URL=http://host.docker.internal:9200
|
||||||
|
- DATABASE_URL=postgresql://postgres:brunix_pass@host.docker.internal:5432/postgres
|
||||||
|
|
||||||
|
- LANGFUSE_HOST=http://45.77.119.180
|
||||||
- LANGFUSE_PUBLIC_KEY=${LANGFUSE_PUBLIC_KEY}
|
- LANGFUSE_PUBLIC_KEY=${LANGFUSE_PUBLIC_KEY}
|
||||||
- LANGFUSE_SECRET_KEY=${LANGFUSE_SECRET_KEY}
|
- LANGFUSE_SECRET_KEY=${LANGFUSE_SECRET_KEY}
|
||||||
- LANGFUSE_HOST=http://langfuse:3000
|
- LLM_BASE_URL=http://host.docker.internal:11434
|
||||||
- OPENAI_API_KEY=${OPENAI_API_KEY} # O el proveedor que elija Ivar
|
- OPENAI_API_KEY=${OPENAI_API_KEY}
|
||||||
depends_on:
|
|
||||||
- elasticsearch
|
extra_hosts:
|
||||||
- langfuse
|
- "host.docker.internal:host-gateway"
|
||||||
networks:
|
|
||||||
- avap-network
|
|
||||||
|
|
||||||
elasticsearch:
|
|
||||||
image: docker.elastic.co/elasticsearch/elasticsearch:8.12.0
|
|
||||||
container_name: brunix-vector-db
|
|
||||||
environment:
|
|
||||||
- discovery.type=single-node
|
|
||||||
- xpack.security.enabled=false
|
|
||||||
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
|
|
||||||
ports:
|
|
||||||
- "9200:9200"
|
|
||||||
networks:
|
|
||||||
- avap-network
|
|
||||||
|
|
||||||
langfuse:
|
|
||||||
image: langfuse/langfuse:2.33.0
|
|
||||||
container_name: brunix-observability
|
|
||||||
ports:
|
|
||||||
- "3000:3000"
|
|
||||||
environment:
|
|
||||||
- DATABASE_URL=postgresql://postgres:brunix_pass@langfuse-db:5432/postgres
|
|
||||||
- NEXTAUTH_URL=http://localhost:3000
|
|
||||||
- NEXTAUTH_SECRET=my_ultra_secret
|
|
||||||
- SALT=my_salt
|
|
||||||
depends_on:
|
|
||||||
- langfuse-db
|
|
||||||
networks:
|
|
||||||
- avap-network
|
|
||||||
|
|
||||||
langfuse-db:
|
|
||||||
image: postgres:15
|
|
||||||
container_name: brunix-postgres
|
|
||||||
environment:
|
|
||||||
- POSTGRES_PASSWORD=brunix_pass
|
|
||||||
volumes:
|
|
||||||
- postgres_data:/var/lib/postgresql/data
|
|
||||||
networks:
|
|
||||||
- avap-network
|
|
||||||
|
|
||||||
networks:
|
|
||||||
avap-network:
|
|
||||||
driver: bridge
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
postgres_data:
|
|
||||||
|
|
|
||||||
|
|
@ -1,70 +1,87 @@
|
||||||
import os
|
import os
|
||||||
import grpc
|
import grpc
|
||||||
from concurrent import futures
|
|
||||||
import logging
|
import logging
|
||||||
|
from concurrent import futures
|
||||||
|
from grpc_reflection.v1alpha import reflection
|
||||||
import brunix_pb2
|
import brunix_pb2
|
||||||
import brunix_pb2_grpc
|
import brunix_pb2_grpc
|
||||||
#from langfuse.callback import CallbackHandler # Descomentar cuando este configurado
|
|
||||||
#from langchain_openai import ChatOpenAI # Cambiar por el que corresponda
|
from langchain_community.llms import Ollama
|
||||||
from langchain_core.messages import HumanMessage
|
from langchain_community.embeddings import OllamaEmbeddings
|
||||||
|
from langchain_elasticsearch import ElasticsearchStore
|
||||||
|
from langchain_core.prompts import ChatPromptTemplate
|
||||||
|
|
||||||
logging.basicConfig(level=logging.INFO)
|
logging.basicConfig(level=logging.INFO)
|
||||||
logger = logging.getLogger("BrunixServer")
|
logger = logging.getLogger("brunix-engine")
|
||||||
|
|
||||||
class BrunixService(brunix_pb2_grpc.AssistanceEngineServicer):
|
class BrunixEngine(brunix_pb2_grpc.AssistanceEngineServicer):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
#self.langfuse_handler = CallbackHandler( # Descomentar cuando este configurado
|
|
||||||
# public_key=os.getenv("LANGFUSE_PUBLIC_KEY"),
|
|
||||||
# secret_key=os.getenv("LANGFUSE_SECRET_KEY"),
|
|
||||||
# host=os.getenv("LANGFUSE_HOST")
|
|
||||||
#)
|
|
||||||
# AQUI IMPLEMENTAR EL MODELO QUE CORRESPONDA - IVAR
|
|
||||||
#self.llm = ChatOpenAI(
|
|
||||||
# model="gpt-4-turbo-preview",
|
|
||||||
# temperature=0.2,
|
|
||||||
# streaming=True
|
|
||||||
#)
|
|
||||||
logger.info("Brunix Engine initializing.")
|
|
||||||
|
|
||||||
def AskAgent(self, request, context): # PLACEHOLDER DE FUNCIONAMIENTO
|
self.base_url = os.getenv("LLM_BASE_URL", "http://ollama-light-service:11434")
|
||||||
logger.info(f"Request received: {request.query}")
|
self.model_name = os.getenv("LLM_MODEL", "qwen2.5:1.5b")
|
||||||
|
|
||||||
|
logger.info(f"Starting server")
|
||||||
|
|
||||||
|
self.llm = Ollama(base_url=self.base_url, model=self.model_name)
|
||||||
|
|
||||||
|
self.embeddings = OllamaEmbeddings(base_url=self.base_url, model="nomic-embed-text")
|
||||||
|
|
||||||
|
es_url = os.getenv("ELASTICSEARCH_URL", "http://elasticsearch:9200")
|
||||||
|
logger.info(f"ElasticSearch on: {es_url}")
|
||||||
|
|
||||||
|
self.vector_store = ElasticsearchStore(
|
||||||
|
es_url=es_url,
|
||||||
|
index_name="avap_manuals",
|
||||||
|
embedding=self.embeddings
|
||||||
|
)
|
||||||
|
|
||||||
|
def AskAgent(self, request, context):
|
||||||
|
logger.info(f"request {request.session_id}): {request.query[:50]}.")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
context_text = "AVAP is a virtual programming language for API development."
|
||||||
config = {"callbacks": [self.langfuse_handler], "run_name": "Brunix_Query"}
|
# 4. Prompt Engineering
|
||||||
|
prompt = ChatPromptTemplate.from_template("""
|
||||||
full_response_text = ""
|
You are Brunix, the 101OBEX artificial intelligence for the AVAP Sphere platform. Respond in a professional manner.
|
||||||
|
|
||||||
chunks = [
|
CONTEXT:
|
||||||
{"text": ""},
|
{context}
|
||||||
]
|
|
||||||
|
|
||||||
for chunk in chunks:
|
QUESTION:
|
||||||
|
{question}
|
||||||
|
""")
|
||||||
|
|
||||||
|
chain = prompt | self.llm
|
||||||
|
|
||||||
|
for chunk in chain.stream({"context": context_text, "question": request.query}):
|
||||||
yield brunix_pb2.AgentResponse(
|
yield brunix_pb2.AgentResponse(
|
||||||
text=chunk["text"],
|
text=str(chunk),
|
||||||
avap_code="",
|
avap_code="AVAP-2026",
|
||||||
node_id=chunk["node"],
|
|
||||||
is_final=False
|
is_final=False
|
||||||
)
|
)
|
||||||
|
|
||||||
yield brunix_pb2.AgentResponse(text="", is_final=True)
|
yield brunix_pb2.AgentResponse(text="", avap_code="", is_final=True)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"AGENT ERROR: {str(e)}")
|
logger.error(f"Error in AskAgent: {str(e)}")
|
||||||
context.set_details(str(e))
|
yield brunix_pb2.AgentResponse(text=f"[Error Motor]: {str(e)}", is_final=True)
|
||||||
context.set_code(grpc.StatusCode.INTERNAL)
|
|
||||||
|
|
||||||
def serve():
|
def serve():
|
||||||
|
|
||||||
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
|
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
|
||||||
brunix_pb2_grpc.add_AssistanceEngineServicer_to_server(BrunixService(), server)
|
|
||||||
|
|
||||||
|
brunix_pb2_grpc.add_AssistanceEngineServicer_to_server(BrunixEngine(), server)
|
||||||
|
|
||||||
|
SERVICE_NAMES = (
|
||||||
|
brunix_pb2.DESCRIPTOR.services_by_name['AssistanceEngine'].full_name,
|
||||||
|
reflection.SERVICE_NAME,
|
||||||
|
)
|
||||||
|
reflection.enable_server_reflection(SERVICE_NAMES, server)
|
||||||
|
|
||||||
server.add_insecure_port('[::]:50051')
|
server.add_insecure_port('[::]:50051')
|
||||||
logger.info("Brunix gRPC Server listen on port 50051")
|
logger.info("Brunix Engine on port 50051")
|
||||||
|
|
||||||
server.start()
|
server.start()
|
||||||
server.wait_for_termination()
|
server.wait_for_termination()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
serve()
|
serve()
|
||||||
Loading…
Reference in New Issue