Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
test-results/
**.log
**/report.html
docker-compose
docker-compose
**/node_modules/
78 changes: 75 additions & 3 deletions app-backend/megaservice.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
import re

# library import
from fastapi import Request
from typing import List
from fastapi import Request, UploadFile, File
from fastapi.responses import StreamingResponse
from dotenv import load_dotenv

Expand Down Expand Up @@ -65,6 +66,7 @@ def __init__(self, host="0.0.0.0", port=8000):
self.host = host
self.port = port
self.endpoint = "/v1/app-backend"
self.is_docsum = False
with open('config/workflow-info.json', 'r') as f:
self.workflow_info = json.load(f)

Expand Down Expand Up @@ -117,6 +119,8 @@ def add_remote_service(self):
if node['inMegaservice']:
print('adding Node', node_id)
microservice_name = node['name'].split('@')[1]
if "docsum" in microservice_name:
self.is_docsum = True
service_node_ip = node_id.split('@')[1].replace('_','-') if USE_NODE_ID_AS_IP else HOST_IP
microservice = templates[microservice_name].get_service(host_ip=service_node_ip, node_id_as_ip=USE_NODE_ID_AS_IP, port=os.getenv(f"{node_id.split('@')[1]}_port", None))
microservice.name = node_id
Expand Down Expand Up @@ -356,7 +360,7 @@ async def handle_request(self, request: Request, megaservice):
for node, response in result_dict.items():
if isinstance(response, StreamingResponse):
return response
last_node = runtime_graph.all_leaves()[-1]
last_node = runtime_graph.all_leaves()[-1] # YX to fix it to the source node of chat completion
print('result_dict:', result_dict)
print('last_node:',last_node)
last_node_info = self.workflow_info['nodes'][last_node]
Expand All @@ -377,9 +381,77 @@ async def handle_request(self, request: Request, megaservice):
# handle the non-llm response
return result_dict[last_node]

async def handle_request_docsum(self, request: Request, files: List[UploadFile] = File(default=None)):
"""Accept pure text, or files .txt/.pdf.docx, audio/video base64 string."""
if "application/json" in request.headers.get("content-type"):
data = await request.json()
stream_opt = data.get("stream", True)
summary_type = data.get("summary_type", "auto")
chunk_size = data.get("chunk_size", -1)
chunk_overlap = data.get("chunk_overlap", -1)
chat_request = ChatCompletionRequest.model_validate(data)
prompt = handle_message(chat_request.messages)

initial_inputs_data = {data["type"]: prompt}

elif "multipart/form-data" in request.headers.get("content-type"):
data = await request.form()
stream_opt = data.get("stream", True)
summary_type = data.get("summary_type", "auto")
chunk_size = data.get("chunk_size", -1)
chunk_overlap = data.get("chunk_overlap", -1)
chat_request = ChatCompletionRequest.model_validate(data)

data_type = data.get("type")

file_summaries = []
if files:
for file in files:
# Fix concurrency issue with the same file name
# https://github.com/opea-project/GenAIExamples/issues/1279
uid = str(uuid.uuid4())
file_path = f"/tmp/{uid}"

import aiofiles

async with aiofiles.open(file_path, "wb") as f:
await f.write(await file.read())

if data_type == "text":
docs = read_text_from_file(file, file_path)
elif data_type in ["audio", "video"]:
docs = encode_file_to_base64(file_path)
else:
raise ValueError(f"Data type not recognized: {data_type}")

os.remove(file_path)

if isinstance(docs, list):
file_summaries.extend(docs)
else:
file_summaries.append(docs)

if file_summaries:
prompt = handle_message(chat_request.messages) + "\n".join(file_summaries)
else:
prompt = handle_message(chat_request.messages)

data_type = data.get("type")
if data_type is not None:
initial_inputs_data = {}
initial_inputs_data[data_type] = prompt
else:
initial_inputs_data = {"messages": prompt}

else:
raise ValueError(f"Unknown request type: {request.headers.get('content-type')}")

def create_handle_request(self, megaservice):
async def handle_request_wrapper(request: Request):
return await self.handle_request(request, megaservice)
if self.is_docsum:
return await self.handle_request_docsum(request)
else:
return await self.handle_request(request, megaservice)
return handle_request_wrapper

def start(self):
Expand Down
17 changes: 8 additions & 9 deletions app-frontend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,20 @@
# SPDX-License-Identifier: Apache-2.0

# Use node 20.11.1 as the base image
FROM node:latest AS vite-app

COPY react /usr/app/react
FROM node:20.11.1 as vite-app
COPY ./react /usr/app/react
WORKDIR /usr/app/react

RUN npm install --legacy-peer-deps && npm run build

FROM nginx:1.27.4-alpine-slim
RUN ["npm", "install"]
RUN ["npm", "run", "build"]


# Install uuidgen in the nginx:alpine image
RUN apk add --no-cache util-linux \
&& apk upgrade --no-cache
FROM nginx:alpine

COPY --from=vite-app /usr/app/react/dist /usr/share/nginx/html
COPY ./react/env.sh /docker-entrypoint.d/env.sh

COPY ./react/nginx.conf /etc/nginx/conf.d/default.conf
RUN chmod +x /docker-entrypoint.d/env.sh
RUN chmod +x /docker-entrypoint.d/env.sh
52 changes: 52 additions & 0 deletions app-frontend/compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Copyright (C) 2024 Intel Corporation
# SPDX-License-Identifier: Apache-2.0

services:
app-frontend:
image: app-frontend:ch
container_name: app-frontend
depends_on:
- chathistory-mongo
ports:
- 5175:80
environment:
- no_proxy=${no_proxy}
- https_proxy=${https_proxy}
- http_proxy=${http_proxy}
- APP_BACKEND_SERVICE_URL=http://localhost:8888/v1/app-backend
- APP_DATAPREP_SERVICE_URL=http://localhost:6007/v1/dataprep
- APP_CHAT_HISTORY_SERVICE_URL=http://localhost:6012/v1/chathistory
- APP_UI_SELECTION=chat,summary,code
ipc: host
restart: always

mongo:
image: mongo:7.0.11
container_name: mongodb
ports:
- 27017:27017
environment:
http_proxy: ${http_proxy}
https_proxy: ${https_proxy}
no_proxy: ${no_proxy}
command: mongod --quiet --logpath /dev/null

chathistory-mongo:
image: ${REGISTRY:-opea}/chathistory-mongo:${TAG:-latest}
container_name: chathistory-mongo-server
ports:
- "6012:6012"
ipc: host
environment:
http_proxy: ${http_proxy}
no_proxy: ${no_proxy}
https_proxy: ${https_proxy}
MONGO_HOST: ${MONGO_HOST:-mongo}
MONGO_PORT: ${MONGO_PORT:-27017}
COLLECTION_NAME: ${COLLECTION_NAME:-Conversations}
LOGFLAG: ${LOGFLAG}
restart: unless-stopped

networks:
default:
driver: bridge
10 changes: 8 additions & 2 deletions app-frontend/react/.env
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
VITE_CHAT_SERVICE_URL=http://backend_address:8899/v1/chatqna
VITE_DATA_PREP_SERVICE_URL=http://backend_address:6007/v1/dataprep
VITE_BACKEND_SERVICE_URL=
VITE_DATAPREP_SERVICE_URL=
VITE_CHAT_HISTORY_SERVICE_URL=
VITE_UI_SELECTION=

VITE_PROMPT_SERVICE_GET_ENDPOINT=
VITE_PROMPT_SERVICE_CREATE_ENDPOINT=
VITE_PROMPT_SERVICE_DELETE_ENDPOINT=
9 changes: 8 additions & 1 deletion app-frontend/react/.env.production
Original file line number Diff line number Diff line change
@@ -1 +1,8 @@
VITE_APP_UUID=APP_UUID
VITE_BACKEND_SERVICE_URL=APP_BACKEND_SERVICE_URL
VITE_DATAPREP_SERVICE_URL=APP_DATAPREP_SERVICE_URL
VITE_CHAT_HISTORY_SERVICE_URL=APP_CHAT_HISTORY_SERVICE_URL
VITE_UI_SELECTION=APP_UI_SELECTION

VITE_PROMPT_SERVICE_GET_ENDPOINT=APP_PROMPT_SERVICE_GET_ENDPOINT
VITE_PROMPT_SERVICE_CREATE_ENDPOINT=APP_PROMPT_SERVICE_CREATE_ENDPOINT
VITE_PROMPT_SERVICE_DELETE_ENDPOINT=APP_PROMPT_SERVICE_DELETE_ENDPOINT
2 changes: 0 additions & 2 deletions app-frontend/react/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

# dependencies
package-lock.json
node_modules
dist
dist-ssr
Expand Down
10 changes: 2 additions & 8 deletions app-frontend/react/env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,6 @@
# Copyright (C) 2024 Intel Corporation
# SPDX-License-Identifier: Apache-2.0

# Generate a random UUID for the application
export APP_UUID=$(uuidgen)

# Print the generated UUID for verification
echo "Generated UUID: $APP_UUID"

for i in $(env | grep APP_) #// Make sure to use the prefix MY_APP_ if you have any other prefix in env.production file variable name replace it with MY_APP_
do
key=$(echo $i | cut -d '=' -f 1)
Expand All @@ -16,6 +10,6 @@ do
# sed All files
# find /usr/share/nginx/html -type f -exec sed -i "s|${key}|${value}|g" '{}' +

# sed JS, CSS, and HTML files
find /usr/share/nginx/html -type f \( -name '*.js' -o -name '*.css' -o -name '*.html' \) -exec sed -i "s|${key}|${value}|g" '{}' +
# sed JS and CSS only
find /usr/share/nginx/html -type f \( -name '*.js' -o -name '*.css' \) -exec sed -i "s|${key}|${value}|g" '{}' +
done
23 changes: 17 additions & 6 deletions app-frontend/react/index.html
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
<!--
Copyright (C) 2024 Intel Corporation
Copyright (C) 2025 Intel Corporation
SPDX-License-Identifier: Apache-2.0
-->

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/src/assets/opea-icon-color.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Conversations UI</title>
<meta charset="utf-8" />
<link rel="shortcut icon" href="/favicon.ico" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap"
rel="stylesheet"
/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="RAG ui for demonstrating LLM functionality" />
<link rel="apple-touch-icon" href="logo192.png" />
<link rel="manifest" href="/manifest.json" />
<title>OPEA Studio APP</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script type="module" src="/src/main.tsx?v=APP_UUID"></script>
<script type="module" src="/src/index.tsx"></script>
</body>
</html>
3 changes: 1 addition & 2 deletions app-frontend/react/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,9 @@ server {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html =404;
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";

location ~* \.(gif|jpe?g|png|webp|ico|svg|css|js|mp4|woff2)$ {
expires 1d;
}
}
}
}
Loading
Loading