From 8d94dd167b5f96c55b966f932d3cd8370ad27b4c Mon Sep 17 00:00:00 2001 From: xtzhang1122 Date: Sun, 18 Aug 2024 23:37:42 +0800 Subject: [PATCH 1/7] init commit Signed-off-by: xtzhang1122 --- src/core/routes/test.py | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/src/core/routes/test.py b/src/core/routes/test.py index de5cd01..30f413b 100644 --- a/src/core/routes/test.py +++ b/src/core/routes/test.py @@ -1,7 +1,9 @@ from typing import List -from fastapi import APIRouter, HTTPException +from fastapi import APIRouter from pydantic import BaseModel -import uuid +import uuid, asyncio +from fastapi.responses import StreamingResponse +from typing import AsyncGenerator router = APIRouter(prefix="/api/test") @@ -37,17 +39,44 @@ def get_hyperledger_fabric_answer(question): # TODO: Get all chats for a user in a paginated format +async def conversation_stream(offset: int = 0, limit: int = 30, order: str = "updated") -> AsyncGenerator[ResponseConversation, None]: + items = list(responses.items())[offset:offset + limit] + for idx, (question, answer) in enumerate(items): + yield ResponseConversation( + id=str(uuid.uuid4()), + message=ResponseMessage( + content=answer, + type=1, + id=str(uuid.uuid4()), + ) + ) + await asyncio.sleep(0.1) # Simulate processing time + @router.post("/conversations") def get_conversations( offset: int = 0, limit: int = 30, order: str = "updated" ) -> ResponseConversation: - pass + return StreamingResponse(conversation_stream(offset, limit), media_type="application/json") # TODO: Get a single chat for a user +async def single_conversation_stream(question: str) -> AsyncGenerator[ResponseConversation, None]: + answer = responses.get(question, "Question not found") + + yield ResponseConversation( + id=str(uuid.uuid4()), + message=ResponseMessage( + content=answer, + type=1, + id=str(uuid.uuid4()), + ) + ) + await asyncio.sleep(0.1) # Simulate processing time + + @router.post("/conversation/{id}") def post_conversation(id: str): - pass + return StreamingResponse(single_conversation_stream(id), media_type="application/json") @router.post("/conversation", response_model=ResponseConversation) @@ -59,4 +88,4 @@ def post_conversation(item: RequestConversation) -> ResponseConversation: type=1, id=str(uuid.uuid4()), ), - ) + ) \ No newline at end of file From 1cc3f15b00539f0175906466afd9a1d51a31ce69 Mon Sep 17 00:00:00 2001 From: xtzhang1122 Date: Sun, 18 Aug 2024 23:43:03 +0800 Subject: [PATCH 2/7] fix formatting Signed-off-by: xtzhang1122 --- src/core/routes/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/routes/test.py b/src/core/routes/test.py index 30f413b..a408302 100644 --- a/src/core/routes/test.py +++ b/src/core/routes/test.py @@ -88,4 +88,4 @@ def post_conversation(item: RequestConversation) -> ResponseConversation: type=1, id=str(uuid.uuid4()), ), - ) \ No newline at end of file + ) From ab926f23149283ee89d433150cf28919838d8500 Mon Sep 17 00:00:00 2001 From: xtzhang1122 Date: Sat, 24 Aug 2024 16:24:17 -0500 Subject: [PATCH 3/7] revision Signed-off-by: xtzhang1122 --- src/core/routes/test.py | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/src/core/routes/test.py b/src/core/routes/test.py index a408302..194f7e7 100644 --- a/src/core/routes/test.py +++ b/src/core/routes/test.py @@ -1,9 +1,9 @@ -from typing import List +from typing import List, AsyncGenerator from fastapi import APIRouter from pydantic import BaseModel import uuid, asyncio from fastapi.responses import StreamingResponse -from typing import AsyncGenerator +import re router = APIRouter(prefix="/api/test") @@ -26,11 +26,11 @@ class RequestConversation(BaseModel): responses = { - "What is Hyperledger Fabric?": "Hyperledger Fabric is an open-source blockchain framework designed for enterprise solutions. It allows for a modular architecture where different components like consensus mechanisms, membership services, and ledger storage can be tailored to specific needs.", - "How to install Hyperledger Fabric?": "To install Hyperledger Fabric, follow these steps:\n1. Install Docker and Docker Compose.\n2. Download the Hyperledger Fabric binaries and docker images using the Fabric CA and Fabric binaries script.\n3. Set up the environment variables for Fabric binaries.\n4. Verify the installation by running Fabric sample network scripts.", - "How to deploy a Hyperledger Fabric network?": "To deploy a Hyperledger Fabric network:\n1. Define the network topology and configuration files (e.g., 'configtx.yaml').\n2. Use the 'fabric-cli' or scripts to create channel artifacts.\n3. Launch the network by starting the necessary Docker containers and services using 'docker-compose' or Kubernetes.\n4. Instantiate and upgrade chaincode as needed.", - "How to run a Hyperledger Fabric network?": "To run a Hyperledger Fabric network:\n1. Start the network by running 'docker-compose up' or the appropriate command for your setup.\n2. Use the Fabric CLI tools or SDKs to interact with the network, including creating and joining channels, and submitting transactions.\n3. Monitor the network's health and performance using Fabric's built-in tools or external monitoring solutions.", - "How to ensure data privacy in Hyperledger Fabric?": "To ensure data privacy in Hyperledger Fabric:\n1. Use private data collections to restrict access to sensitive data.\n2. Implement access control policies and endorsement policies.\n3. Utilize encryption for data at rest and in transit.\n4. Regularly review and update security configurations and practices.", + "what is hyperledger fabric": "Hyperledger Fabric is an open-source blockchain framework designed for enterprise solutions. It allows for a modular architecture where different components like consensus mechanisms, membership services, and ledger storage can be tailored to specific needs.", + "how to install hyperledger fabric": "To install Hyperledger Fabric, follow these steps:\n1. Install Docker and Docker Compose.\n2. Download the Hyperledger Fabric binaries and docker images using the Fabric CA and Fabric binaries script.\n3. Set up the environment variables for Fabric binaries.\n4. Verify the installation by running Fabric sample network scripts.", + "how to deploy a hyperledger fabric network": "To deploy a Hyperledger Fabric network:\n1. Define the network topology and configuration files (e.g., 'configtx.yaml').\n2. Use the 'fabric-cli' or scripts to create channel artifacts.\n3. Launch the network by starting the necessary Docker containers and services using 'docker-compose' or Kubernetes.\n4. Instantiate and upgrade chaincode as needed.", + "how to run a hyperledger fabric network": "To run a Hyperledger Fabric network:\n1. Start the network by running 'docker-compose up' or the appropriate command for your setup.\n2. Use the Fabric CLI tools or SDKs to interact with the network, including creating and joining channels, and submitting transactions.\n3. Monitor the network's health and performance using Fabric's built-in tools or external monitoring solutions.", + "how to ensure data privacy in hyperledger fabric": "To ensure data privacy in Hyperledger Fabric:\n1. Use private data collections to restrict access to sensitive data.\n2. Implement access control policies and endorsement policies.\n3. Utilize encryption for data at rest and in transit.\n4. Regularly review and update security configurations and practices.", } @@ -38,11 +38,21 @@ def get_hyperledger_fabric_answer(question): return responses.get(question, "Question not found in the database.") -# TODO: Get all chats for a user in a paginated format +def normalize_question(question: str) -> str: + # Convert to lowercase and strip punctuation + question = question.rstrip() + return re.sub(r'[^\w\s]', '', question.lower()) + + async def conversation_stream(offset: int = 0, limit: int = 30, order: str = "updated") -> AsyncGenerator[ResponseConversation, None]: - items = list(responses.items())[offset:offset + limit] - for idx, (question, answer) in enumerate(items): - yield ResponseConversation( + # Normalize the keys in the responses dictionary + normalized_responses = {normalize_question(k): v for k, v in responses.items()} + + # Retrieve items based on offset and limit + items = list(normalized_responses.items())[offset:offset + limit] + + for idx, (_, answer) in enumerate(items): + conversation = ResponseConversation( id=str(uuid.uuid4()), message=ResponseMessage( content=answer, @@ -50,8 +60,10 @@ async def conversation_stream(offset: int = 0, limit: int = 30, order: str = "up id=str(uuid.uuid4()), ) ) + yield f"data: {conversation.json()}\n\n" await asyncio.sleep(0.1) # Simulate processing time + @router.post("/conversations") def get_conversations( offset: int = 0, limit: int = 30, order: str = "updated" @@ -59,11 +71,11 @@ def get_conversations( return StreamingResponse(conversation_stream(offset, limit), media_type="application/json") -# TODO: Get a single chat for a user async def single_conversation_stream(question: str) -> AsyncGenerator[ResponseConversation, None]: + question = normalize_question(question) answer = responses.get(question, "Question not found") - yield ResponseConversation( + conversation = ResponseConversation( id=str(uuid.uuid4()), message=ResponseMessage( content=answer, @@ -71,6 +83,7 @@ async def single_conversation_stream(question: str) -> AsyncGenerator[ResponseCo id=str(uuid.uuid4()), ) ) + yield f"data: {conversation.json()}\n\n" await asyncio.sleep(0.1) # Simulate processing time From 439b8721bf1b6701f6bb313f830f8633f8d6bee6 Mon Sep 17 00:00:00 2001 From: xtzhang1122 Date: Mon, 26 Aug 2024 10:13:46 -0500 Subject: [PATCH 4/7] align response types Signed-off-by: xtzhang1122 --- src/core/routes/test.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/core/routes/test.py b/src/core/routes/test.py index 194f7e7..2dafa6c 100644 --- a/src/core/routes/test.py +++ b/src/core/routes/test.py @@ -67,8 +67,20 @@ async def conversation_stream(offset: int = 0, limit: int = 30, order: str = "up @router.post("/conversations") def get_conversations( offset: int = 0, limit: int = 30, order: str = "updated" -) -> ResponseConversation: - return StreamingResponse(conversation_stream(offset, limit), media_type="application/json") +) -> List[ResponseConversation]: + normalized_responses = {normalize_question(k): v for k, v in responses.items()} + items = list(normalized_responses.items())[offset:offset + limit] + conversations = [ + ResponseConversation( + id=str(uuid.uuid4()), + message=ResponseMessage( + content=answer, + type=1, + id=str(uuid.uuid4()), + ) + ) for _, answer in items + ] + return conversations async def single_conversation_stream(question: str) -> AsyncGenerator[ResponseConversation, None]: From e7e21ea6d3e4377acdaef04708e032e50d6e0060 Mon Sep 17 00:00:00 2001 From: xtzhang1122 Date: Fri, 30 Aug 2024 16:17:53 -0500 Subject: [PATCH 5/7] revision Signed-off-by: xtzhang1122 --- src/core/routes/test.py | 82 +++++++++++++---------------------------- 1 file changed, 26 insertions(+), 56 deletions(-) diff --git a/src/core/routes/test.py b/src/core/routes/test.py index 2dafa6c..5fc208c 100644 --- a/src/core/routes/test.py +++ b/src/core/routes/test.py @@ -34,83 +34,53 @@ class RequestConversation(BaseModel): } -def get_hyperledger_fabric_answer(question): - return responses.get(question, "Question not found in the database.") - - def normalize_question(question: str) -> str: # Convert to lowercase and strip punctuation question = question.rstrip() return re.sub(r'[^\w\s]', '', question.lower()) -async def conversation_stream(offset: int = 0, limit: int = 30, order: str = "updated") -> AsyncGenerator[ResponseConversation, None]: - # Normalize the keys in the responses dictionary - normalized_responses = {normalize_question(k): v for k, v in responses.items()} - - # Retrieve items based on offset and limit - items = list(normalized_responses.items())[offset:offset + limit] - - for idx, (_, answer) in enumerate(items): - conversation = ResponseConversation( +def create_conversation_response(content: str) -> ResponseConversation: + return ResponseConversation( + id=str(uuid.uuid4()), + message=ResponseMessage( + content=content, + type=1, id=str(uuid.uuid4()), - message=ResponseMessage( - content=answer, - type=1, - id=str(uuid.uuid4()), - ) ) - yield f"data: {conversation.json()}\n\n" - await asyncio.sleep(0.1) # Simulate processing time + ) -@router.post("/conversations") +@router.get("/conversations", response_model=List[ResponseConversation]) def get_conversations( offset: int = 0, limit: int = 30, order: str = "updated" ) -> List[ResponseConversation]: normalized_responses = {normalize_question(k): v for k, v in responses.items()} items = list(normalized_responses.items())[offset:offset + limit] - conversations = [ - ResponseConversation( - id=str(uuid.uuid4()), - message=ResponseMessage( - content=answer, - type=1, - id=str(uuid.uuid4()), - ) - ) for _, answer in items - ] - return conversations + return [create_conversation_response(answer) for _, answer in items] -async def single_conversation_stream(question: str) -> AsyncGenerator[ResponseConversation, None]: - question = normalize_question(question) + +@router.get("/conversation/{id}", response_model=ResponseConversation) +def get_single_conversation(id: str) -> ResponseConversation: + question = normalize_question(id) answer = responses.get(question, "Question not found") - conversation = ResponseConversation( - id=str(uuid.uuid4()), - message=ResponseMessage( - content=answer, - type=1, - id=str(uuid.uuid4()), - ) - ) - yield f"data: {conversation.json()}\n\n" - await asyncio.sleep(0.1) # Simulate processing time + return create_conversation_response(answer) -@router.post("/conversation/{id}") -def post_conversation(id: str): - return StreamingResponse(single_conversation_stream(id), media_type="application/json") +async def single_conversation_stream(question: str) -> AsyncGenerator[str, None]: + question = normalize_question(question) + answer = responses.get(question, "Question not found") + conversation = create_conversation_response(answer) + yield f"data: {conversation.json()}\n\n" + await asyncio.sleep(0.1) -@router.post("/conversation", response_model=ResponseConversation) -def post_conversation(item: RequestConversation) -> ResponseConversation: - return ResponseConversation( - id=item.id, - message=ResponseMessage( - content=get_hyperledger_fabric_answer(item.content), - type=1, - id=str(uuid.uuid4()), - ), + +@router.post("/conversation") +async def post_conversation(item: RequestConversation) -> StreamingResponse: + return StreamingResponse( + single_conversation_stream(item.content), + media_type="text/event-stream" ) From f2c87b054c86738fc7e09610c34293bfec70552e Mon Sep 17 00:00:00 2001 From: xtzhang1122 Date: Tue, 3 Sep 2024 13:29:54 -0500 Subject: [PATCH 6/7] revise formatting Signed-off-by: xtzhang1122 --- src/core/routes/test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/routes/test.py b/src/core/routes/test.py index 5fc208c..8e5c370 100644 --- a/src/core/routes/test.py +++ b/src/core/routes/test.py @@ -1,7 +1,8 @@ from typing import List, AsyncGenerator from fastapi import APIRouter from pydantic import BaseModel -import uuid, asyncio +import uuid +import asyncio from fastapi.responses import StreamingResponse import re @@ -35,7 +36,6 @@ class RequestConversation(BaseModel): def normalize_question(question: str) -> str: - # Convert to lowercase and strip punctuation question = question.rstrip() return re.sub(r'[^\w\s]', '', question.lower()) From 3aaca465dd59dd1dc719e6bd9c4a0002ef41b1ca Mon Sep 17 00:00:00 2001 From: xtzhang1122 Date: Tue, 3 Sep 2024 13:34:15 -0500 Subject: [PATCH 7/7] revise formatting Signed-off-by: xtzhang1122 --- src/core/routes/test.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/core/routes/test.py b/src/core/routes/test.py index 8e5c370..27f373b 100644 --- a/src/core/routes/test.py +++ b/src/core/routes/test.py @@ -37,7 +37,7 @@ class RequestConversation(BaseModel): def normalize_question(question: str) -> str: question = question.rstrip() - return re.sub(r'[^\w\s]', '', question.lower()) + return re.sub(r"[^\w\s]", "", question.lower()) def create_conversation_response(content: str) -> ResponseConversation: @@ -47,7 +47,7 @@ def create_conversation_response(content: str) -> ResponseConversation: content=content, type=1, id=str(uuid.uuid4()), - ) + ), ) @@ -56,7 +56,7 @@ def get_conversations( offset: int = 0, limit: int = 30, order: str = "updated" ) -> List[ResponseConversation]: normalized_responses = {normalize_question(k): v for k, v in responses.items()} - items = list(normalized_responses.items())[offset:offset + limit] + items = list(normalized_responses.items())[offset : offset + limit] return [create_conversation_response(answer) for _, answer in items] @@ -81,6 +81,5 @@ async def single_conversation_stream(question: str) -> AsyncGenerator[str, None] @router.post("/conversation") async def post_conversation(item: RequestConversation) -> StreamingResponse: return StreamingResponse( - single_conversation_stream(item.content), - media_type="text/event-stream" + single_conversation_stream(item.content), media_type="text/event-stream" )