15 | {I18N.components.Crash.woMenSiHuYu}
16 | {I18N.components.Crash.qingChangShiShuaXin}
你已完成登录。可以继续输入了。
27 | 28 | } 29 | 30 | export default LoginCard; 31 | -------------------------------------------------------------------------------- /client/public/images/statistic.svg: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /migrations/supabase/migrations/20241224030938_remote_schema.sql: -------------------------------------------------------------------------------- 1 | set check_function_bodies = off; 2 | 3 | CREATE OR REPLACE FUNCTION public.analyze_user_token_usage(start_date date, end_date date) 4 | RETURNS TABLE(bot_id text, usage_date date, input_tokens bigint, output_tokens bigint, total_tokens bigint) 5 | LANGUAGE plpgsql 6 | AS $function$ 7 | BEGIN 8 | RETURN QUERY 9 | SELECT 10 | u.bot_id AS bot_id, 11 | u.date AS usage_date, -- 使用别名来避免歧义 12 | SUM(u.input_token)::BIGINT AS input_tokens, -- 将结果转换为 BIGINT 13 | SUM(u.output_token)::BIGINT AS output_tokens, -- 将结果转换为 BIGINT 14 | SUM(u.total_token)::BIGINT AS total_tokens -- 将结果转换为 BIGINT 15 | FROM user_token_usage u 16 | WHERE 17 | u.date >= start_date AND 18 | u.date <= end_date 19 | GROUP BY u.date, u.bot_id; 20 | END; 21 | $function$ 22 | ; 23 | 24 | 25 | -------------------------------------------------------------------------------- /server/agent/bot/bot_builder.py: -------------------------------------------------------------------------------- 1 | from typing import AsyncIterator 2 | from agent.llm.clients.openai import OpenAIClient 3 | from core.type_class.data_class import ChatData 4 | 5 | from agent.base import AgentBuilder, dict_to_sse 6 | from agent.prompts.bot_builder import generate_prompt_by_user_id 7 | from agent.tools import bot_builder 8 | 9 | TOOL_MAPPING = { 10 | "create_bot": bot_builder.create_bot, 11 | "edit_bot": bot_builder.edit_bot, 12 | } 13 | 14 | 15 | def agent_stream_chat( 16 | input_data: ChatData, 17 | user_id: str, 18 | bot_id: str, 19 | ) -> AsyncIterator[str]: 20 | prompt = generate_prompt_by_user_id(user_id, bot_id) 21 | agent = AgentBuilder( 22 | chat_model=OpenAIClient(), 23 | prompt=prompt, 24 | tools=TOOL_MAPPING, 25 | enable_tavily=False, 26 | ) 27 | return dict_to_sse(agent.run_stream_chat(input_data)) 28 | -------------------------------------------------------------------------------- /server/utils/private_key/s3.py: -------------------------------------------------------------------------------- 1 | import boto3 2 | from botocore.exceptions import ClientError 3 | from utils.env import get_env_variable 4 | from utils.private_key.base import BasePrivateKeyProvider 5 | 6 | REGION_NAME = get_env_variable("AWS_REGION") 7 | 8 | 9 | class S3PrivateKeyProvider(BasePrivateKeyProvider): 10 | def get_private_key(self, secret_id: str) -> str: 11 | session = boto3.session.Session() 12 | client = session.client(service_name="secretsmanager", region_name=REGION_NAME) 13 | try: 14 | get_secret_value_response = client.get_secret_value(SecretId=secret_id) 15 | except ClientError as e: 16 | # For a list of exceptions thrown, see 17 | # https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html 18 | raise e 19 | 20 | return get_secret_value_response["SecretString"] -------------------------------------------------------------------------------- /client/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "strict": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "noEmit": true, 14 | "esModuleInterop": true, 15 | "module": "esnext", 16 | "moduleResolution": "node", 17 | "isolatedModules": true, 18 | "jsx": "preserve", 19 | "incremental": true, 20 | "plugins": [ 21 | { 22 | "name": "next" 23 | } 24 | ], 25 | "paths": { 26 | "@/*": [ 27 | "./*" 28 | ] 29 | }, 30 | "resolveJsonModule": true 31 | }, 32 | "include": [ 33 | "next-env.d.ts", 34 | "**/*.ts", 35 | "**/*.tsx", 36 | ".next/types/**/*.ts" 37 | ], 38 | "exclude": [ 39 | "node_modules" 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /client/public/icons/SaveIcon.tsx: -------------------------------------------------------------------------------- 1 | const SaveIcon = () => ( 2 | 13 | ); 14 | export default SaveIcon; 15 | -------------------------------------------------------------------------------- /assistant/src/icons/ThunderIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | export const ThunderIcon = () => { 3 | return ( 4 | 18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /docker/Dockerfile.aws.lambda: -------------------------------------------------------------------------------- 1 | FROM public.ecr.aws/docker/library/python:3.12.0-slim-bullseye 2 | 3 | LABEL org.opencontainers.image.source=https://github.com/petercat-ai/petercat 4 | LABEL org.opencontainers.image.description="Petercat Container Image" 5 | LABEL org.opencontainers.image.licenses=MIT 6 | 7 | # Copy aws-lambda-adapter for Steaming response 8 | COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.8.1 /lambda-adapter /opt/extensions/lambda-adapter 9 | 10 | # Copy nltk_lambda_layer for using nltk in lambda 11 | COPY --from=petercatai/nltk-layer:1.0.1 /nltk_data /opt/nltk_data 12 | 13 | # Copy function code 14 | COPY . ${LAMBDA_TASK_ROOT} 15 | # from your project folder. 16 | COPY requirements.txt . 17 | RUN pip3 install -r requirements.txt --target "${LAMBDA_TASK_ROOT}" -U --no-cache-dir 18 | 19 | # Set NLTK_DATA to load nltk_data 20 | ENV NLTK_DATA=/opt/nltk_data 21 | 22 | CMD ["python", "main.py"] 23 | -------------------------------------------------------------------------------- /server/tests/mock_session.py: -------------------------------------------------------------------------------- 1 | import json 2 | from base64 import b64encode 3 | from itsdangerous import TimestampSigner 4 | from core.models.user import User 5 | from utils.env import get_env_variable 6 | 7 | session_secret_key = get_env_variable("FASTAPI_SECRET_KEY") 8 | 9 | 10 | def create_session_cookie(data) -> str: 11 | signer = TimestampSigner(str(session_secret_key)) 12 | 13 | return signer.sign( 14 | b64encode(json.dumps(data).encode("utf-8")), 15 | ).decode("utf-8") 16 | 17 | 18 | mock_user = User( 19 | id="1", 20 | sub="1", 21 | sid="1", 22 | avatar="1", 23 | picture="1", 24 | nickname="1", 25 | access_token="1", 26 | anonymous=False, 27 | agreement_accepted=False, 28 | ) 29 | 30 | 31 | def get_mock_user(): 32 | return mock_user 33 | 34 | 35 | def mock_session(): 36 | return {"session": create_session_cookie({"user": dict(mock_user)})} 37 | -------------------------------------------------------------------------------- /client/sentry.client.config.js: -------------------------------------------------------------------------------- 1 | import * as Sentry from "@sentry/nextjs"; 2 | 3 | Sentry.init({ 4 | dsn: "https://25cd1bf180d345e9c926589cd0ca0353@o4507910955597824.ingest.us.sentry.io/4507910957432832", 5 | // Replay may only be enabled for the client-side 6 | integrations: [Sentry.replayIntegration()], 7 | 8 | // Set tracesSampleRate to 1.0 to capture 100% 9 | // of transactions for tracing. 10 | // We recommend adjusting this value in production 11 | tracesSampleRate: 1.0, 12 | 13 | // Capture Replay for 10% of all sessions, 14 | // plus for 100% of sessions with an error 15 | replaysSessionSampleRate: 0.1, 16 | replaysOnErrorSampleRate: 1.0, 17 | 18 | // ... 19 | 20 | // Note: if you want to override the automatic release value, do not set a 21 | // `release` value here - use the environment variable `SENTRY_RELEASE`, so 22 | // that it will also get attached to your source maps 23 | }); 24 | -------------------------------------------------------------------------------- /assistant/src/Chat/components/UserContent.tsx: -------------------------------------------------------------------------------- 1 | import { Image } from 'antd'; 2 | import React, { type FC } from 'react'; 3 | import { ImageURLContentBlock } from '../../interface'; 4 | import MarkdownRender from './MarkdownRender'; 5 | 6 | interface IProps { 7 | images: ImageURLContentBlock[]; 8 | text: string; 9 | } 10 | 11 | const UserContent: FC{children};
18 | }
19 |
20 | return (
21 |