diff --git a/client/package.json b/client/package.json index e85bc5bd..0ab0ed9d 100644 --- a/client/package.json +++ b/client/package.json @@ -39,7 +39,7 @@ "lottie-react": "^2.4.0", "next": "14.0.1", "openai": "^4.24.7", - "petercat-lui": "^0.0.20", + "petercat-lui": "^0.0.21", "postcss": "8.4.27", "react": "18.2.0", "react-dom": "18.2.0", diff --git a/client/yarn.lock b/client/yarn.lock index 1358df65..3bca4215 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -11252,10 +11252,10 @@ pbkdf2@^3.0.3, pbkdf2@^3.1.2: safe-buffer "^5.0.1" sha.js "^2.4.8" -petercat-lui@^0.0.20: - version "0.0.20" - resolved "https://registry.npmjs.org/petercat-lui/-/petercat-lui-0.0.20.tgz#aff16b3b83480456322adbf78e0e055ae23c82bf" - integrity sha512-3w3+aTlVMxx3r3cPRRRzGwK6RZjXDtnoSMfurMorDw+JisrZY+qn2Cmkl3vD/gvxXzZUxULQf0u302KTDAMr5A== +petercat-lui@^0.0.21: + version "0.0.21" + resolved "https://registry.npmjs.org/petercat-lui/-/petercat-lui-0.0.21.tgz#6d1298240a6e05ac8dda9c722c1d6f45cbc89250" + integrity sha512-iA++PRanPYB7Sg4lKa7mLVDIFwGB/yFfw4X/BykJfMYvYZZSDPRmhqsRH1FbHviHSsgpVi2WthRHCDizbrOUFg== dependencies: "@ant-design/icons" "^5.3.5" "@ant-design/pro-chat" "^1.9.0" diff --git a/lui/package.json b/lui/package.json index c05515b8..aa4d40c4 100644 --- a/lui/package.json +++ b/lui/package.json @@ -1,6 +1,6 @@ { "name": "petercat-lui", - "version": "0.0.20", + "version": "0.0.21", "description": "A react library developed with dumi", "module": "dist/index.js", "types": "dist/index.d.ts", diff --git a/lui/src/services/ChatController.ts b/lui/src/services/ChatController.ts index 68bf6084..7cb4b513 100644 --- a/lui/src/services/ChatController.ts +++ b/lui/src/services/ChatController.ts @@ -14,6 +14,7 @@ export async function streamChat( ): Promise { return fetch(`${apiDomain}${apiUrl}`, { method: 'POST', + credentials: 'include', headers: { 'Content-Type': 'application/json', connection: 'keep-alive', diff --git a/server/agent/base.py b/server/agent/base.py index 0132e080..dec39303 100644 --- a/server/agent/base.py +++ b/server/agent/base.py @@ -27,9 +27,7 @@ def __init__( tools: Dict[str, Callable], enable_tavily: Optional[bool] = True, temperature: Optional[int] = 0.2, - max_tokens: Optional[int] = 1500, - bot_id: Optional[str] = None, - uid: Optional[str] = None + max_tokens: Optional[int] = 1500 ): """ @class `Builde AgentExecutor based on tools and prompt` @@ -38,14 +36,10 @@ def __init__( @param enable_tavily: Optional[bool] If set True, enables the Tavily tool @param temperature: Optional[int] @param max_tokens: Optional[int] - @param bot_id: Optional[str] - @param uid: Optional[str] """ self.prompt = prompt self.tools = tools self.enable_tavily = enable_tavily - self.bot_id = bot_id - self.uid = uid self.temperature = temperature self.max_tokens = max_tokens self.agent_executor = self._create_agent_with_tools() @@ -60,10 +54,6 @@ def _create_agent_with_tools(self) -> AgentExecutor: llm = ChatOpenAI(model="gpt-4o", temperature=self.temperature, streaming=True, max_tokens=self.max_tokens, openai_api_key=OPEN_API_KEY) tools = self.init_tavily_tools() if self.enable_tavily else [] - - # for tool in self.tools.items(): - # wrapped_tool = lambda input_data: tool(input_data, self.user_id, self.bot_id) - # tools.append(wrapped_tool) for tool in self.tools.values(): tools.append(tool) diff --git a/server/agent/bot_builder.py b/server/agent/bot_builder.py index ec9669ac..f3adb59c 100644 --- a/server/agent/bot_builder.py +++ b/server/agent/bot_builder.py @@ -1,35 +1,9 @@ from typing import AsyncIterator, Optional from data_class import ChatData from agent.base import AgentBuilder +from prompts.bot_builder import generate_prompt_by_user_id from tools import bot_builder -PROMPT = """ -## Role: -You are a GitHub Answering Bot Creation Assistant. You specialize in creating a Q&A bot based on the information of a GitHub repository provided by the user. - -## Skills: - -Skill 1: Retrieve GitHub Repository Name - -- Guide users to provide their GitHub repository name or URL. -- Extract the GitHub repository name from the provided GitHub URL - -Skill 2: Create a Q&A Bot - -- Use the create_bot tool to create a bot based on the - GitHub repository name provided by the user. - -Skill 3: Modify Bot Configuration - -- Utilize the edit_bot tool to modify the bot's configuration information based on the user's description. -- Always use the created bot's ID as the id of the bot being edited and the user's ID as the uid. -- If the user wishes to change the avatar, ask user to provide the URL of the new avatar. - -## Limitations: - -- Can only create a Q&A bot or update the configuration of the bot based on the GitHub repository information provided by the user. -- During the process of creating a Q&A bot, if any issues or errors are encountered, you may provide related advice or solutions, but must not directly modify the user's GitHub repository. -- When modifying the bot's configuration information, you must adhere to the user's suggestions and requirements and not make changes without permission. -""" TOOL_MAPPING = { @@ -37,6 +11,7 @@ "edit_bot": bot_builder.edit_bot, } -def agent_stream_chat(input_data: ChatData, user_id: str, bot_id: Optional[str] = None ) -> AsyncIterator[str]: - agent = AgentBuilder(prompt=PROMPT, tools=TOOL_MAPPING, enable_tavily=False, bot_id=bot_id, uid=user_id) +def agent_stream_chat(input_data: ChatData, user_id: str, bot_id: Optional[str] = None) -> AsyncIterator[str]: + prompt = generate_prompt_by_user_id(user_id, bot_id) + agent = AgentBuilder(prompt=prompt, tools=TOOL_MAPPING, enable_tavily=False) return agent.run_stream_chat(input_data) diff --git a/server/main.py b/server/main.py index b6206ad4..643435d7 100644 --- a/server/main.py +++ b/server/main.py @@ -1,7 +1,7 @@ import os import uvicorn -from fastapi import FastAPI, Cookie, Request, HTTPException +from fastapi import FastAPI from fastapi.responses import JSONResponse, StreamingResponse, RedirectResponse from starlette.middleware.sessions import SessionMiddleware from fastapi.middleware.cors import CORSMiddleware diff --git a/server/prompts/bot_builder.py b/server/prompts/bot_builder.py new file mode 100644 index 00000000..3bf09879 --- /dev/null +++ b/server/prompts/bot_builder.py @@ -0,0 +1,52 @@ +CREATE_PROMPT = """ +## Role: +You are a GitHub Answering Bot Creation Assistant. You specialize in creating a Q&A bot based on the information of a GitHub repository provided by the user. + +## Skills: + +Skill 1: Retrieve GitHub Repository Name + +- Guide users to provide their GitHub repository name or URL. +- Extract the GitHub repository name from the provided GitHub URL + +Skill 2: Create a Q&A Bot + +- Use the create_bot tool to create a bot based on the GitHub repository name provided by the user. +- The uid of the current user is {user_id} + +Skill 3: Modify Bot Configuration + +- Utilize the edit_bot tool to modify the bot's configuration information based on the user's description. +- Always use the created bot's ID as the id of the bot being edited and the user's ID as the uid. +- If the user wishes to change the avatar, ask user to provide the URL of the new avatar. + +## Limitations: + +- Can only create a Q&A bot or update the configuration of the bot based on the GitHub repository information provided by the user. +- During the process of creating a Q&A bot, if any issues or errors are encountered, you may provide related advice or solutions, but must not directly modify the user's GitHub repository. +- When modifying the bot's configuration information, you must adhere to the user's suggestions and requirements and not make changes without permission. +""" + +EDIT_PROMPT = """ +## Role: +You are a GitHub Answering Bot modifying assistant. You specialize in modifying the configuration of a Q&A bot based on the user's requirements. + +## Skills: + +- Utilize the edit_bot tool to modify the bot's configuration information based on the user's description. +- Always use the created bot's ID: {bot_id} as the id of the bot being edited and the uid of the current user is {user_id}. +- If the user wishes to change the avatar, ask user to provide the URL of the new avatar. + +## Limitations: + +- Can only update the configuration of the bot based on the GitHub repository information provided by the user. +- During the process of a Q&A bot, if any issues or errors are encountered, you may provide related advice or solutions, but must not directly modify the user's GitHub repository. +- When modifying the bot's configuration information, you must adhere to the user's suggestions and requirements and not make changes without permission. +""" + + +def generate_prompt_by_user_id(user_id: str, bot_id: str): + if bot_id: + return EDIT_PROMPT.format(bot_id=bot_id, user_id=user_id) + else: + return CREATE_PROMPT.format(user_id=user_id) diff --git a/server/routers/chat.py b/server/routers/chat.py index 346add4b..2e56e198 100644 --- a/server/routers/chat.py +++ b/server/routers/chat.py @@ -1,4 +1,4 @@ -import json +import asyncio from typing import Optional from fastapi import APIRouter, Cookie, Depends from fastapi.responses import StreamingResponse @@ -13,6 +13,10 @@ responses={404: {"description": "Not found"}}, ) +async def generate_auth_failed_stream(): + message = "Auth failed, please login first\n\n" + yield message + @router.post("/stream_qa", response_class=StreamingResponse, dependencies=[Depends(verify_rate_limit)]) def run_qa_chat(input_data: ChatData): result = qa_chat.agent_stream_chat(input_data) @@ -26,6 +30,8 @@ async def run_issue_helper(input_data: ChatData): @router.post("/stream_builder", response_class=StreamingResponse, dependencies=[Depends(verify_rate_limit)]) def run_bot_builder(input_data: ChatData, user_id: str = Cookie(None), bot_id: Optional[str] = None): + if not user_id: + return StreamingResponse(generate_auth_failed_stream(), media_type="text/event-stream") result = bot_builder.agent_stream_chat(input_data, user_id, bot_id) return StreamingResponse(result, media_type="text/event-stream") diff --git a/server/tools/bot_builder.py b/server/tools/bot_builder.py index 46a98b21..aff89c61 100644 --- a/server/tools/bot_builder.py +++ b/server/tools/bot_builder.py @@ -13,7 +13,7 @@ @tool async def create_bot( repo_name: str, - uid: str = 123456789, + uid: str, starters: Optional[List[str]] = None, hello_message: Optional[str] = None, ): diff --git a/server/verify/rate_limit.py b/server/verify/rate_limit.py index b6dc56f0..59ed28e5 100644 --- a/server/verify/rate_limit.py +++ b/server/verify/rate_limit.py @@ -17,8 +17,6 @@ async def verify_rate_limit(petercat: str = Cookie(None)): if not petercat: raise HTTPException(status_code=403, detail="Must Login") user = await getUserInfoByToken(petercat) - user_id = user['id'] - supabase = get_client() table = supabase.table("user_token_usage") rows = table.select('id, user_id, last_request, request_count').eq('user_id', user_id).execute() @@ -47,4 +45,4 @@ async def verify_rate_limit(petercat: str = Cookie(None)): table.upsert(user_usage).execute() - return user \ No newline at end of file + return user