diff --git a/comps/chathistory/arango/Dockerfile b/comps/chathistory/arango/Dockerfile new file mode 100644 index 000000000..5a8db3973 --- /dev/null +++ b/comps/chathistory/arango/Dockerfile @@ -0,0 +1,36 @@ +# Copyright (C) 2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +FROM python:3.11-slim + +ENV LANG=C.UTF-8 + +# Install system dependencies +RUN apt-get update -y && apt-get install -y --no-install-recommends --fix-missing \ + build-essential \ + libjemalloc-dev \ + libgl1-mesa-glx + +# Install Python packages globally + + +# Create user +RUN useradd -m -s /bin/bash user && \ + mkdir -p /home/user/comps/chathistory/arango && \ + chown -R user /home/user + +USER user + +COPY comps /home/user/comps +COPY requirements.txt /home/user/ + +RUN pip install --no-cache-dir --upgrade pip setuptools && \ + pip install --no-cache-dir -r /home/user/comps/chathistory/arango/requirements.txt && \ + pip install --no-cache-dir -r /home/user/requirements.txt + +ENV PYTHONPATH=/home/user/ + +WORKDIR /home/user/comps/chathistory/arango +RUN pip install -r requirements.txt + +ENTRYPOINT ["python", "chathistory_arango.py"] diff --git a/comps/chathistory/arango/README.md b/comps/chathistory/arango/README.md new file mode 100644 index 000000000..ee78fc1d8 --- /dev/null +++ b/comps/chathistory/arango/README.md @@ -0,0 +1,109 @@ +# 📝 Chat History Microservice with MongoDB + +This README provides setup guides and all the necessary information about the Chat History microservice with MongoDB database. + +--- + +## Setup Environment Variables + +```bash +export http_proxy=${your_http_proxy} +export https_proxy=${your_http_proxy} +export MONGO_HOST=${MONGO_HOST} +export MONGO_PORT=27017 +export DB_NAME=${DB_NAME} +export COLLECTION_NAME=${COLLECTION_NAME} +``` + +--- + +## 🚀Start Microservice with Docker + +### Build Docker Image + +```bash +cd ../../../../ +docker build -t opea/chathistory-mongo-server:latest --build-arg https_proxy=$https_proxy --build-arg http_proxy=$http_proxy -f comps/chathistory/mongo/Dockerfile . +``` + +### Run Docker with CLI + +- Run MongoDB image container + + ```bash + docker run -d -p 27017:27017 --name=mongo mongo:latest + ``` + +- Run the Chat History microservice + + ```bash + docker run -d --name="chathistory-mongo-server" -p 6012:6012 -e http_proxy=$http_proxy -e https_proxy=$https_proxy -e no_proxy=$no_proxy -e MONGO_HOST=${MONGO_HOST} -e MONGO_PORT=${MONGO_PORT} -e DB_NAME=${DB_NAME} -e COLLECTION_NAME=$ {COLLECTION_NAME} opea/chathistory-mongo-server:latest + ``` + +--- + +## ✅ Invoke Microservice + +The Chat History microservice exposes the following API endpoints: + +- Create new chat conversation + + ```bash + curl -X 'POST' \ + http://${host_ip}:6012/v1/chathistory/create \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -d '{ + "data": { + "messages": "test Messages", "user": "test" + } + }' + ``` + +- Get all the Conversations for a user + + ```bash + curl -X 'POST' \ + http://${host_ip}:6012/v1/chathistory/get \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -d '{ + "user": "test"}' + ``` + +- Get a specific conversation by id. + + ```bash + curl -X 'POST' \ + http://localhost:6012/v1/chathistory/get \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -d '{ + "user": "test", "id":"673255bad3e51a6fdef12b5e"}' + ``` + +- Update the conversation by id. + + ```bash + curl -X 'POST' \ + http://localhost:6012/v1/chathistory/create \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -d '{ + "data": { + "messages": "test Messages Update", "user": "test" + }, + "id":"673255bad3e51a6fdef12b5e" + }' + ``` + +- Delete a stored conversation. + + ```bash + curl -X 'POST' \ + http://${host_ip}:6012/v1/chathistory/delete \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -d '{ + "user": "test", "id":"668620173180b591e1e0cd74"}' + ``` diff --git a/comps/chathistory/arango/arango_conn.py b/comps/chathistory/arango/arango_conn.py new file mode 100644 index 000000000..98d355f3e --- /dev/null +++ b/comps/chathistory/arango/arango_conn.py @@ -0,0 +1,45 @@ +# Copyright (C) 2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +# import motor.motor_asyncio as motor +from arango import ArangoClient as PythonArangoClient +from config import DB_NAME, ARANGODB_HOST, ARANGODB_PORT, ARANGODB_PASSWORD, ARANGODB_USERNAME + +class ArangoClient: + conn_url = f"http://{ARANGODB_HOST}:{ARANGODB_PORT}/" + + @staticmethod + def get_db_client(): + try: + # Create client + print(f"Connecting to database: {ArangoClient.conn_url}, username: {ARANGODB_USERNAME}, password: {ARANGODB_PASSWORD}, db: {DB_NAME}") + client = PythonArangoClient(hosts=ArangoClient.conn_url) + + # First connect to _system database + sys_db = client.db( + '_system', + username=ARANGODB_USERNAME, + password=ARANGODB_PASSWORD, + verify=True + ) + print("Connected to _system database") + + # Create target database if it doesn't exist + if not sys_db.has_database(DB_NAME): + sys_db.create_database(DB_NAME) + print(f"Created database {DB_NAME}") + + # Now connect to the target database + db = client.db( + DB_NAME, + username=ARANGODB_USERNAME, + password=ARANGODB_PASSWORD, + verify=True + ) + print(f"Connected to database {DB_NAME}") + + return db + + except Exception as e: + print(f"Failed to connect to database: {str(e)}, url: {ArangoClient.conn_url}, username: {ARANGODB_USERNAME}, password: {ARANGODB_PASSWORD}, db: {DB_NAME}") + raise e diff --git a/comps/chathistory/arango/arango_store.py b/comps/chathistory/arango/arango_store.py new file mode 100644 index 000000000..b41f2c273 --- /dev/null +++ b/comps/chathistory/arango/arango_store.py @@ -0,0 +1,161 @@ +# # Copyright (C) 2024 Intel Corporation +# # SPDX-License-Identifier: Apache-2.0 + +from config import COLLECTION_NAME +from arango_conn import ArangoClient +from pydantic import BaseModel + +class DocumentStore: + + def __init__( + self, + user: str, + ): + self.user = user + + def initialize_storage(self) -> None: + try: + self.db_client = ArangoClient.get_db_client() + # Create collection if it doesn't exist + print(COLLECTION_NAME) + if not self.db_client.has_collection(COLLECTION_NAME): + print("Creating collection") + self.collection = self.db_client.create_collection(COLLECTION_NAME) + else: + print("Collection already exists") + self.collection = self.db_client.collection(COLLECTION_NAME) + + print(f"Successfully initialized storage with collection: {COLLECTION_NAME}") + + except Exception as e: + print(f"Failed to initialize storage: {e}, url: {ArangoClient.conn_url}, collection: {COLLECTION_NAME}") + raise Exception(f"Storage initialization failed: {e}, url: {ArangoClient.conn_url}, collection: {COLLECTION_NAME}") + + def save_document(self, document: BaseModel) -> str: + """Stores a new document into the storage. + + Args: + document: The document to be stored. It should be a Pydantic model. + + Returns: + str: The ID of the inserted document. + + Raises: + Exception: If an error occurs while storing the document. + """ + try: + inserted_conv = self.collection.insert( + document.model_dump(by_alias=True, mode="json", exclude={"id"}) + ) + document_id = str(inserted_conv["_key"]) + return document_id + + except Exception as e: + print(e) + raise Exception(e) + + def update_document(self, document_id, updated_data, first_query) -> str: + """Updates a document in the collection with the given document_id. + + Args: + document_id (str): The ID of the document to update. + updated_data (object): The updated data to be set in the document. + first_query (object): The first query to be set in the document. + + Returns: + bool: True if the document was successfully updated, False otherwise. + + Raises: + KeyError: If an invalid document_id is provided. + Exception: If an error occurs during the update process. + """ + try: + cursor = self.db_client.aql.execute(f""" + FOR doc IN @@collection + FILTER doc._key == @document_id AND doc.data.user == @user + LIMIT 1 + UPDATE doc WITH @body IN @@collection + OPTIONS {{ keepNull: @keep_none, mergeObjects: @merge }} + """, + bind_vars={"@collection": self.collection.name, "document_id": document_id, "user": self.user, "body": {"data": updated_data.model_dump(by_alias=True, mode="json"), "first_query": first_query}, "keep_none": True, "merge": True} + ) + return "Updated document : {}".format(document_id) + + except Exception as e: + print(e) + raise Exception(e) + + def get_all_documents_of_user(self) -> list[dict]: + """Retrieves all documents of a specific user from the collection. + + Returns: + A list of dictionaries representing the conversation documents. + Raises: + Exception: If there is an error while retrieving the documents. + """ + conversation_list: list = [] + try: + cursor = self.db_client.aql.execute(""" + FOR doc IN @@collection + FILTER doc.data.user == @user + RETURN doc + """, + bind_vars={"@collection": self.collection.name, "user": self.user} + ) + for document in cursor: + document["id"] = document["_key"] + del document["_key"] + del document["_id"] + del document["_rev"] + del document["data"] + conversation_list.append(document) + return conversation_list + + except Exception as e: + print(e) + raise Exception(e) + + def get_user_documents_by_id(self, document_id) -> dict | None: + """Retrieves a user document from the collection based on the given document ID. + + Args: + document_id (str): The ID of the document to retrieve. + + Returns: + dict | None: The user document if found, None otherwise. + """ + try: + response = self.collection.get(document_id) + if response and response['data']["user"] == self.user: + response.pop("_id", None) + return response + return None + + except Exception as e: + print(e) + raise Exception(e) + + def delete_document(self, document_id) -> str: + """Deletes a document from the collection based on the provided document ID. + + Args: + document_id (str): The ID of the document to be deleted. + + Returns: + bool: True if the document is successfully deleted, False otherwise. + + Raises: + KeyError: If the provided document ID is invalid. + Exception: If an error occurs during the deletion process. + """ + try: + doc = self.collection.get(document_id) + if doc and doc['data']["user"] == self.user: + self.collection.delete(document_id) + return "Deleted document : {}".format(document_id) + else: + raise Exception("Not able to delete the Document") + + except Exception as e: + print(e) + raise Exception(e) diff --git a/comps/chathistory/arango/arango_store_async.py b/comps/chathistory/arango/arango_store_async.py new file mode 100644 index 000000000..1eac50a1b --- /dev/null +++ b/comps/chathistory/arango/arango_store_async.py @@ -0,0 +1,208 @@ +# # Copyright (C) 2024 Intel Corporation +# # SPDX-License-Identifier: Apache-2.0 + + +from config import COLLECTION_NAME, ARANGODB_USERNAME, ARANGODB_PASSWORD, DB_NAME +from arango_conn import ArangoClient +from pydantic import BaseModel + + +class TestDocument(BaseModel): + messages: str + user: str + +class DocumentStore: + + def __init__( + self, + user: str, + ): + self.user = user + + def initialize_storage(self) -> None: + try: + self.db_client = ArangoClient.get_db_client() + # Create collection if it doesn't exist + if not self.db_client.has_collection(COLLECTION_NAME): + self.collection = self.db_client.create_collection(COLLECTION_NAME) + else: + self.collection = self.db_client.collection(COLLECTION_NAME) + + print(f"Successfully initialized storage with collection: {COLLECTION_NAME}") + + except Exception as e: + print(f"Failed to initialize storage: {e}, url: {ArangoClient.conn_url}, username: {ARANGODB_USERNAME}, password: {ARANGODB_PASSWORD}, db: {DB_NAME}") + raise Exception(f"Storage initialization failed: {e}, collection: {COLLECTION_NAME}") + + async def save_document(self, document: BaseModel) -> str: + """Stores a new document into the storage. + + Args: + document: The document to be stored. It should be a Pydantic model. + + Returns: + str: The ID of the inserted document. + + Raises: + Exception: If an error occurs while storing the document. + """ + try: + inserted_conv = self.collection.insert( + document.model_dump(by_alias=True, mode="json", exclude={"id"}) + ) + document_id = str(inserted_conv["_key"]) + return document_id + + except Exception as e: + print(e) + raise Exception(e) + + async def update_document(self, document_id, updated_data, first_query) -> str: + """Updates a document in the collection with the given document_id. + + Args: + document_id (str): The ID of the document to update. + updated_data (object): The updated data to be set in the document. + first_query (object): The first query to be set in the document. + + Returns: + bool: True if the document was successfully updated, False otherwise. + + Raises: + KeyError: If an invalid document_id is provided. + Exception: If an error occurs during the update process. + """ + try: + update_result = self.collection.update( + {"_key": document_id, "data.user": self.user}, + {"data": updated_data.model_dump(by_alias=True, mode="json"), "first_query": first_query} + ) + if update_result: + return "Updated document : {}".format(document_id) + else: + raise Exception("Not able to Update the Document") + + except Exception as e: + print(e) + raise Exception(e) + + async def get_all_documents_of_user(self) -> list[dict]: + """Retrieves all documents of a specific user from the collection. + + Returns: + A list of dictionaries representing the conversation documents. + Raises: + Exception: If there is an error while retrieving the documents. + """ + conversation_list: list = [] + try: + cursor = self.collection.find({"data.user": self.user}, {"data": 0}) + for document in cursor: + document["id"] = document["_key"] + conversation_list.append(document) + return conversation_list + + except Exception as e: + print(e) + raise Exception(e) + + async def get_user_documents_by_id(self, document_id) -> dict | None: + """Retrieves a user document from the collection based on the given document ID. + + Args: + document_id (str): The ID of the document to retrieve. + + Returns: + dict | None: The user document if found, None otherwise. + """ + try: + response = self.collection.get(document_id) + print(response) + breakpoint() + if response and response["user"] == self.user: + response.pop("_id", None) + return response + return None + + except Exception as e: + print(e) + raise Exception(e) + + async def delete_document(self, document_id) -> str: + """Deletes a document from the collection based on the provided document ID. + + Args: + document_id (str): The ID of the document to be deleted. + + Returns: + bool: True if the document is successfully deleted, False otherwise. + + Raises: + KeyError: If the provided document ID is invalid. + Exception: If an error occurs during the deletion process. + """ + try: + doc = self.collection.get(document_id) + if doc and doc["user"] == self.user: + self.collection.delete(document_id) + return "Deleted document : {}".format(document_id) + else: + raise Exception("Not able to delete the Document") + + except Exception as e: + print(e) + raise Exception(e) + +if __name__ == "__main__": + import bson.errors as BsonError + from bson.objectid import ObjectId + from config import COLLECTION_NAME + from arango_conn import ArangoClient + from pydantic import BaseModel + import asyncio + print("Starting tests...") + store = DocumentStore("test_user") + store.initialize_storage() + breakpoint() + test_doc = TestDocument( + messages="test message", + user="test_user" + ) + + # Test save document + def test_save(): + doc_id = store.save_document(test_doc) + print(f"Saved document ID: {doc_id}") + return doc_id + + # Test get document + def test_get(doc_id): + doc = store.get_user_documents_by_id(doc_id) + print(f"Retrieved document: {doc}") + return doc + + # # Test delete document + # def test_delete(doc_id): + # result = store.delete_document(doc_id) + # print(f"Delete result: {result}") + + #test update document + def test_update(doc_id): + result = store.update_document(doc_id, test_doc, "test query") + print(f"Update result: {result}") + return result + + def run_tests(): + # Run save test + doc_id = test_save() + breakpoint() + + # Run get test + print(test_get(doc_id)) + breakpoint() + # Run delete test + # print(test_delete(doc_id)) + print(test_update(doc_id)) + breakpoint() + run_tests() + diff --git a/comps/chathistory/arango/chathistory_arango.py b/comps/chathistory/arango/chathistory_arango.py new file mode 100644 index 000000000..c07b98d01 --- /dev/null +++ b/comps/chathistory/arango/chathistory_arango.py @@ -0,0 +1,148 @@ +# Copyright (C) 2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +import os +from typing import Optional + +from fastapi import HTTPException +from arango_store import DocumentStore +from pydantic import BaseModel + +from comps import CustomLogger +from comps.cores.mega.micro_service import opea_microservices, register_microservice +from comps.cores.proto.api_protocol import ChatCompletionRequest + +logger = CustomLogger("chathistory_arango") +logflag = os.getenv("LOGFLAG", False) + + +class ChatMessage(BaseModel): + data: ChatCompletionRequest + first_query: Optional[str] = None + id: Optional[str] = None + + +class ChatId(BaseModel): + user: str + id: Optional[str] = None + + +def get_first_string(value): + if isinstance(value, str): + return value + elif isinstance(value, list): + # Assuming we want the first string from the first dictionary + if value and isinstance(value[0], dict): + first_dict = value[0] + if first_dict: + # Get the first value from the dictionary + first_key = next(iter(first_dict)) + return first_dict[first_key] + + +@register_microservice( + name="opea_service@chathistory_arango", + endpoint="/v1/chathistory/create", + host="0.0.0.0", + input_datatype=ChatMessage, + port=6012, +) +def create_documents(document: ChatMessage): + """Creates or updates a document in the document store. + + Args: + document (ChatMessage): The ChatMessage object containing the data to be stored. + + Returns: + The result of the operation if successful, None otherwise. + """ + if logflag: + logger.info(document) + try: + if document.data.user is None: + raise HTTPException(status_code=500, detail="Please provide the user information") + store = DocumentStore(document.data.user) + store.initialize_storage() + if document.first_query is None: + document.first_query = get_first_string(document.data.messages) + if document.id: + res = store.update_document(document.id, document.data, document.first_query) + else: + res = store.save_document(document) + if logflag: + logger.info(res) + return res + except Exception as e: + logger.info(f"An error occurred: {str(e)}") + raise HTTPException(status_code=500, detail=str(e)) + + +@register_microservice( + name="opea_service@chathistory_arango", + endpoint="/v1/chathistory/get", + host="0.0.0.0", + input_datatype=ChatId, + port=6012, +) +def get_documents(document: ChatId): + """Retrieves documents from the document store based on the provided ChatId. + + Args: + document (ChatId): The ChatId object containing the user and optional document id. + + Returns: + The retrieved documents if successful, None otherwise. + """ + if logflag: + logger.info(document) + try: + store = DocumentStore(document.user) + store.initialize_storage() + if document.id is None: + res = store.get_all_documents_of_user() + else: + res = store.get_user_documents_by_id(document.id) + if logflag: + logger.info(res) + return res + except Exception as e: + # Handle the exception here + logger.info(f"An error occurred: {str(e)}") + raise HTTPException(status_code=500, detail=str(e)) + + +@register_microservice( + name="opea_service@chathistory_arango", + endpoint="/v1/chathistory/delete", + host="0.0.0.0", + input_datatype=ChatId, + port=6012, +) +def delete_documents(document: ChatId): + """Deletes a document from the document store based on the provided ChatId. + + Args: + document (ChatId): The ChatId object containing the user and document id. + + Returns: + The result of the deletion if successful, None otherwise. + """ + if logflag: + logger.info(document) + try: + store = DocumentStore(document.user) + store.initialize_storage() + if document.id is None: + raise Exception("Document id is required.") + else: + res = store.delete_document(document.id) + if logflag: + logger.info(res) + return res + except Exception as e: + # Handle the exception here + logger.info(f"An error occurred: {str(e)}") + raise HTTPException(status_code=500, detail=str(e)) + + +if __name__ == "__main__": + opea_microservices["opea_service@chathistory_arango"].start() \ No newline at end of file diff --git a/comps/chathistory/arango/chathistory_arango_async.py b/comps/chathistory/arango/chathistory_arango_async.py new file mode 100644 index 000000000..2478607a4 --- /dev/null +++ b/comps/chathistory/arango/chathistory_arango_async.py @@ -0,0 +1,149 @@ +# Copyright (C) 2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +import os +from typing import Optional + +from fastapi import HTTPException +from arango_store import DocumentStore +from pydantic import BaseModel + +from comps import CustomLogger +from comps.cores.mega.micro_service import opea_microservices, register_microservice +from comps.cores.proto.api_protocol import ChatCompletionRequest + +logger = CustomLogger("chathistory_arango") +logflag = os.getenv("LOGFLAG", False) + + +class ChatMessage(BaseModel): + data: ChatCompletionRequest + first_query: Optional[str] = None + id: Optional[str] = None + + +class ChatId(BaseModel): + user: str + id: Optional[str] = None + + +def get_first_string(value): + if isinstance(value, str): + return value + elif isinstance(value, list): + # Assuming we want the first string from the first dictionary + if value and isinstance(value[0], dict): + first_dict = value[0] + if first_dict: + # Get the first value from the dictionary + first_key = next(iter(first_dict)) + return first_dict[first_key] + + +@register_microservice( + name="opea_service@chathistory_arango", + endpoint="/v1/chathistory/create", + host="0.0.0.0", + input_datatype=ChatMessage, + port=6012, +) +async def create_documents(document: ChatMessage): + """Creates or updates a document in the document store. + + Args: + document (ChatMessage): The ChatMessage object containing the data to be stored. + + Returns: + The result of the operation if successful, None otherwise. + """ + if logflag: + logger.info(document) + try: + if document.data.user is None: + raise HTTPException(status_code=500, detail="Please provide the user information") + store = DocumentStore(document.data.user) + store.initialize_storage() + if document.first_query is None: + document.first_query = get_first_string(document.data.messages) + if document.id: + res = await store.update_document(document.id, document.data, document.first_query) + else: + res = await store.save_document(document) + if logflag: + logger.info(res) + return res + except Exception as e: + logger.info(f"An error occurred: {str(e)}") + raise HTTPException(status_code=500, detail=str(e)) + + +@register_microservice( + name="opea_service@chathistory_arango", + endpoint="/v1/chathistory/get", + host="0.0.0.0", + input_datatype=ChatId, + port=6012, +) +async def get_documents(document: ChatId): + """Retrieves documents from the document store based on the provided ChatId. + + Args: + document (ChatId): The ChatId object containing the user and optional document id. + + Returns: + The retrieved documents if successful, None otherwise. + """ + if logflag: + logger.info(document) + try: + store = DocumentStore(document.user) + store.initialize_storage() + if document.id is None: + res = await store.get_all_documents_of_user() + else: + res = await store.get_user_documents_by_id(document.id) + if logflag: + logger.info(res) + return res + except Exception as e: + # Handle the exception here + logger.info(f"An error occurred: {str(e)}") + raise HTTPException(status_code=500, detail=str(e)) + + +@register_microservice( + name="opea_service@chathistory_arango", + endpoint="/v1/chathistory/delete", + host="0.0.0.0", + input_datatype=ChatId, + port=6012, +) +async def delete_documents(document: ChatId): + """Deletes a document from the document store based on the provided ChatId. + + Args: + document (ChatId): The ChatId object containing the user and document id. + + Returns: + The result of the deletion if successful, None otherwise. + """ + if logflag: + logger.info(document) + try: + store = DocumentStore(document.user) + store.initialize_storage() + if document.id is None: + raise Exception("Document id is required.") + else: + res = await store.delete_document(document.id) + if logflag: + logger.info(res) + return res + except Exception as e: + # Handle the exception here + logger.info(f"An error occurred: {str(e)}") + raise HTTPException(status_code=500, detail=str(e)) + + +if __name__ == "__main__": + opea_microservices["opea_service@chathistory_arango"].start() + # create_documents(ChatMessage(data=ChatCompletionRequest(user="test", messages="test Messages"), first_query=None)) \ No newline at end of file diff --git a/comps/chathistory/arango/config.py b/comps/chathistory/arango/config.py new file mode 100644 index 000000000..67f8117b3 --- /dev/null +++ b/comps/chathistory/arango/config.py @@ -0,0 +1,12 @@ +# Copyright (C) 2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import os + +# ARANGO configuration +ARANGODB_HOST = os.getenv("ARANGODB_HOST", "localhost") +ARANGODB_PORT = os.getenv("ARANGODB_PORT", 8529) +ARANGODB_USERNAME = os.getenv("ARANGODB_USERNAME", "root") +ARANGODB_PASSWORD = os.getenv("ARANGODB_PASSWORD", "test") +DB_NAME = os.getenv("DB_NAME", "OPEA") +COLLECTION_NAME = os.getenv("COLLECTION_NAME", "ChatHistory") \ No newline at end of file diff --git a/comps/chathistory/arango/docker-compose-chathistory-arango.yaml b/comps/chathistory/arango/docker-compose-chathistory-arango.yaml new file mode 100644 index 000000000..64e7a4458 --- /dev/null +++ b/comps/chathistory/arango/docker-compose-chathistory-arango.yaml @@ -0,0 +1,33 @@ +# Copyright (C) 2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +version: "3" +services: + arangodb: + image: arangodb:3.12.1 + container_name: arangodb + ports: + - 8529:8529 + environment: + http_proxy: ${http_proxy} + https_proxy: ${https_proxy} + no_proxy: ${no_proxy} + command: arangod --quiet --logpath /dev/null + chathistory-arango: + image: opea/chathistory-arango-server:latest + container_name: chathistory-arango-server + ports: + - "6012:6012" + ipc: host + environment: + http_proxy: ${http_proxy} + no_proxy: ${no_proxy} + https_proxy: ${https_proxy} + ARANGODB_HOST: ${ARANGODB_HOST} + ARANGODB_PORT: ${ARANGODB_PORT} + COLLECTION_NAME: ${COLLECTION_NAME} + restart: unless-stopped + +networks: + default: + driver: bridge diff --git a/comps/chathistory/arango/requirements.txt b/comps/chathistory/arango/requirements.txt new file mode 100644 index 000000000..9e5d0de8e --- /dev/null +++ b/comps/chathistory/arango/requirements.txt @@ -0,0 +1 @@ +python-arango \ No newline at end of file