Spaces:
Runtime error
Runtime error
Upload 21 files
Browse files- Dockerfile +11 -0
- __pycache__/app.cpython-39.pyc +0 -0
- app.py +216 -0
- chainlit.md +14 -0
- functions/FunctionManager.py +168 -0
- functions/__init__.py +0 -0
- functions/__pycache__/FunctionManager.cpython-39.pyc +0 -0
- functions/__pycache__/__init__.cpython-39.pyc +0 -0
- plugins/.DS_Store +0 -0
- plugins/common/__pycache__/functions.cpython-39.pyc +0 -0
- plugins/common/config.json +3 -0
- plugins/common/functions.py +63 -0
- plugins/python/__pycache__/executor.cpython-39.pyc +0 -0
- plugins/python/__pycache__/functions.cpython-39.pyc +0 -0
- plugins/python/config.json +3 -0
- plugins/python/executor.py +93 -0
- plugins/python/functions.py +52 -0
- plugins/vue/__pycache__/functions.cpython-39.pyc +0 -0
- plugins/vue/config.json +3 -0
- plugins/vue/functions.py +103 -0
- requirements.txt +8 -0
Dockerfile
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.9
|
| 2 |
+
RUN useradd -m -u 1000 user
|
| 3 |
+
USER user
|
| 4 |
+
ENV HOME=/home/user \
|
| 5 |
+
PATH=/home/user/.local/bin:$PATH
|
| 6 |
+
WORKDIR $HOME/app
|
| 7 |
+
COPY --chown=user . $HOME/app
|
| 8 |
+
COPY ./requirements.txt ~/app/requirements.txt
|
| 9 |
+
RUN pip install -r requirements.txt
|
| 10 |
+
COPY . .
|
| 11 |
+
CMD ["chainlit", "run", "app.py", "--port", "7860"]
|
__pycache__/app.cpython-39.pyc
ADDED
|
Binary file (4.43 kB). View file
|
|
|
app.py
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import openai
|
| 2 |
+
import json
|
| 3 |
+
import ast
|
| 4 |
+
import os
|
| 5 |
+
import chainlit as cl
|
| 6 |
+
from functions.FunctionManager import FunctionManager
|
| 7 |
+
import inspect
|
| 8 |
+
import os
|
| 9 |
+
import tiktoken
|
| 10 |
+
import importlib
|
| 11 |
+
import json
|
| 12 |
+
from chainlit import user_session
|
| 13 |
+
|
| 14 |
+
# Get all subdirectories under the 'plugins' directory, ignoring directories named '__pycache__'
|
| 15 |
+
plugin_dirs = [d for d in os.listdir('plugins')
|
| 16 |
+
if os.path.isdir(os.path.join('plugins', d)) and d != '__pycache__']
|
| 17 |
+
|
| 18 |
+
functions = []
|
| 19 |
+
|
| 20 |
+
# Iterate through each subdirectory (i.e., each plugin)
|
| 21 |
+
for dir in plugin_dirs:
|
| 22 |
+
# Try to read the plugin's configuration file
|
| 23 |
+
try:
|
| 24 |
+
with open(f'plugins/{dir}/config.json', 'r') as f:
|
| 25 |
+
config = json.load(f)
|
| 26 |
+
enabled = config.get('enabled', True)
|
| 27 |
+
except FileNotFoundError:
|
| 28 |
+
# If the configuration file does not exist, we assume this plugin should be imported
|
| 29 |
+
enabled = True
|
| 30 |
+
|
| 31 |
+
# Check if this plugin should be imported
|
| 32 |
+
if not enabled:
|
| 33 |
+
continue
|
| 34 |
+
|
| 35 |
+
# Dynamically import each plugin's functions module
|
| 36 |
+
module = importlib.import_module(f'plugins.{dir}.functions')
|
| 37 |
+
|
| 38 |
+
# Get all functions in the module and add them to the functions list
|
| 39 |
+
functions.extend([
|
| 40 |
+
obj for name, obj in inspect.getmembers(module)
|
| 41 |
+
if inspect.isfunction(obj)
|
| 42 |
+
])
|
| 43 |
+
|
| 44 |
+
function_manager = FunctionManager(functions=functions)
|
| 45 |
+
print("functions:", function_manager.generate_functions_array())
|
| 46 |
+
|
| 47 |
+
max_tokens = 5000
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
def __truncate_conversation(conversation) -> None:
|
| 51 |
+
"""
|
| 52 |
+
Truncate the conversation
|
| 53 |
+
"""
|
| 54 |
+
# Take the first one out
|
| 55 |
+
system_con = conversation[0]
|
| 56 |
+
# Remove the first one
|
| 57 |
+
conversation = conversation[1:]
|
| 58 |
+
while True:
|
| 59 |
+
if (get_token_count(conversation) > max_tokens
|
| 60 |
+
and len(conversation) > 1):
|
| 61 |
+
# Don't remove the first message
|
| 62 |
+
conversation.pop(1)
|
| 63 |
+
else:
|
| 64 |
+
break
|
| 65 |
+
# Add the first one back
|
| 66 |
+
conversation.insert(0, system_con)
|
| 67 |
+
return conversation
|
| 68 |
+
|
| 69 |
+
# https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
def get_token_count(conversation) -> int:
|
| 73 |
+
"""
|
| 74 |
+
Get token count
|
| 75 |
+
"""
|
| 76 |
+
encoding = tiktoken.encoding_for_model('gpt-3.5-turbo')
|
| 77 |
+
|
| 78 |
+
num_tokens = 0
|
| 79 |
+
for message in conversation:
|
| 80 |
+
# every message follows <im_start>{role/name}\n{content}<im_end>\n
|
| 81 |
+
num_tokens += 4
|
| 82 |
+
for key, value in message.items():
|
| 83 |
+
num_tokens += len(encoding.encode(str(value)))
|
| 84 |
+
if key == "name": # if there's a name, the role is omitted
|
| 85 |
+
num_tokens += -1 # role is always required and always 1 token
|
| 86 |
+
num_tokens += 2 # every reply is primed with <im_start>assistant
|
| 87 |
+
return num_tokens
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
MAX_ITER = 5
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
async def on_message(user_message: object):
|
| 94 |
+
print("==================================")
|
| 95 |
+
print(user_message)
|
| 96 |
+
print("==================================")
|
| 97 |
+
user_message = str(user_message)
|
| 98 |
+
message_history = cl.user_session.get("message_history")
|
| 99 |
+
message_history.append({"role": "user", "content": user_message})
|
| 100 |
+
|
| 101 |
+
cur_iter = 0
|
| 102 |
+
|
| 103 |
+
while cur_iter < MAX_ITER:
|
| 104 |
+
|
| 105 |
+
# OpenAI call
|
| 106 |
+
openai_message = {"role": "", "content": ""}
|
| 107 |
+
function_ui_message = None
|
| 108 |
+
content_ui_message = cl.Message(content="")
|
| 109 |
+
stream_resp = None
|
| 110 |
+
send_message = __truncate_conversation(message_history)
|
| 111 |
+
try:
|
| 112 |
+
async for stream_resp in await openai.ChatCompletion.acreate(
|
| 113 |
+
model="gpt-3.5-turbo",
|
| 114 |
+
messages=send_message,
|
| 115 |
+
stream=True,
|
| 116 |
+
function_call="auto",
|
| 117 |
+
functions=function_manager.generate_functions_array(),
|
| 118 |
+
temperature=0.3
|
| 119 |
+
): # type: ignore
|
| 120 |
+
new_delta = stream_resp.choices[0]["delta"]
|
| 121 |
+
openai_message, content_ui_message, function_ui_message = await process_new_delta(
|
| 122 |
+
new_delta, openai_message, content_ui_message,
|
| 123 |
+
function_ui_message)
|
| 124 |
+
except Exception as e:
|
| 125 |
+
print(e)
|
| 126 |
+
cur_iter += 1
|
| 127 |
+
continue
|
| 128 |
+
|
| 129 |
+
if stream_resp is None:
|
| 130 |
+
break
|
| 131 |
+
|
| 132 |
+
message_history.append(openai_message)
|
| 133 |
+
if function_ui_message is not None:
|
| 134 |
+
await function_ui_message.send()
|
| 135 |
+
|
| 136 |
+
if stream_resp.choices[0]["finish_reason"] == "stop":
|
| 137 |
+
break
|
| 138 |
+
elif stream_resp.choices[0]["finish_reason"] != "function_call":
|
| 139 |
+
raise ValueError(stream_resp.choices[0]["finish_reason"])
|
| 140 |
+
# if code arrives here, it means there is a function call
|
| 141 |
+
function_name = openai_message.get("function_call").get("name")
|
| 142 |
+
print(openai_message.get("function_call"))
|
| 143 |
+
try:
|
| 144 |
+
arguments = json.loads(
|
| 145 |
+
openai_message.get("function_call").get("arguments"))
|
| 146 |
+
except:
|
| 147 |
+
arguments = ast.literal_eval(
|
| 148 |
+
openai_message.get("function_call").get("arguments"))
|
| 149 |
+
|
| 150 |
+
function_response = await function_manager.call_function(
|
| 151 |
+
function_name, arguments)
|
| 152 |
+
# print(function_response)
|
| 153 |
+
|
| 154 |
+
message_history.append({
|
| 155 |
+
"role": "function",
|
| 156 |
+
"name": function_name,
|
| 157 |
+
"content": function_response,
|
| 158 |
+
})
|
| 159 |
+
|
| 160 |
+
await cl.Message(
|
| 161 |
+
author=function_name,
|
| 162 |
+
content=str(function_response),
|
| 163 |
+
language="json",
|
| 164 |
+
indent=1,
|
| 165 |
+
).send()
|
| 166 |
+
cur_iter += 1
|
| 167 |
+
|
| 168 |
+
|
| 169 |
+
async def process_new_delta(new_delta, openai_message, content_ui_message,
|
| 170 |
+
function_ui_message):
|
| 171 |
+
if "role" in new_delta:
|
| 172 |
+
openai_message["role"] = new_delta["role"]
|
| 173 |
+
if "content" in new_delta:
|
| 174 |
+
new_content = new_delta.get("content") or ""
|
| 175 |
+
openai_message["content"] += new_content
|
| 176 |
+
await content_ui_message.stream_token(new_content)
|
| 177 |
+
if "function_call" in new_delta:
|
| 178 |
+
if "name" in new_delta["function_call"]:
|
| 179 |
+
openai_message["function_call"] = {
|
| 180 |
+
"name": new_delta["function_call"]["name"]
|
| 181 |
+
}
|
| 182 |
+
await content_ui_message.send()
|
| 183 |
+
function_ui_message = cl.Message(
|
| 184 |
+
author=new_delta["function_call"]["name"],
|
| 185 |
+
content="",
|
| 186 |
+
indent=1,
|
| 187 |
+
language="json")
|
| 188 |
+
await function_ui_message.stream_token(
|
| 189 |
+
new_delta["function_call"]["name"])
|
| 190 |
+
|
| 191 |
+
if "arguments" in new_delta["function_call"]:
|
| 192 |
+
if "arguments" not in openai_message["function_call"]:
|
| 193 |
+
openai_message["function_call"]["arguments"] = ""
|
| 194 |
+
openai_message["function_call"]["arguments"] += new_delta[
|
| 195 |
+
"function_call"]["arguments"]
|
| 196 |
+
await function_ui_message.stream_token(
|
| 197 |
+
new_delta["function_call"]["arguments"])
|
| 198 |
+
return openai_message, content_ui_message, function_ui_message
|
| 199 |
+
|
| 200 |
+
|
| 201 |
+
@cl.on_chat_start
|
| 202 |
+
def start_chat():
|
| 203 |
+
cl.user_session.set(
|
| 204 |
+
"message_history",
|
| 205 |
+
[{
|
| 206 |
+
"role": "system",
|
| 207 |
+
"content": """
|
| 208 |
+
you are now chatting with an AI assistant. The assistant is helpful, creative, clever, and very friendly.
|
| 209 |
+
"""
|
| 210 |
+
}],
|
| 211 |
+
)
|
| 212 |
+
|
| 213 |
+
|
| 214 |
+
@cl.on_message
|
| 215 |
+
async def run_conversation(user_message: object):
|
| 216 |
+
await on_message(user_message)
|
chainlit.md
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Welcome to Chainlit! 🚀🤖
|
| 2 |
+
|
| 3 |
+
Hi there, Developer! 👋 We're excited to have you on board. Chainlit is a powerful tool designed to help you prototype, debug and share applications built on top of LLMs.
|
| 4 |
+
|
| 5 |
+
## Useful Links 🔗
|
| 6 |
+
|
| 7 |
+
- **Documentation:** Get started with our comprehensive [Chainlit Documentation](https://docs.chainlit.io) 📚
|
| 8 |
+
- **Discord Community:** Join our friendly [Chainlit Discord](https://discord.gg/ZThrUxbAYw) to ask questions, share your projects, and connect with other developers! 💬
|
| 9 |
+
|
| 10 |
+
We can't wait to see what you create with Chainlit! Happy coding! 💻😊
|
| 11 |
+
|
| 12 |
+
## Welcome screen
|
| 13 |
+
|
| 14 |
+
To modify the welcome screen, edit the `chainlit.md` file at the root of your project. If you do not want a welcome screen, just leave this file empty.
|
functions/FunctionManager.py
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import inspect
|
| 2 |
+
import json
|
| 3 |
+
import re
|
| 4 |
+
|
| 5 |
+
import requests
|
| 6 |
+
import openai
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
class FunctionManager:
|
| 10 |
+
def __init__(self, functions=None):
|
| 11 |
+
self.functions = {}
|
| 12 |
+
self.excluded_functions = {'inspect', 'create_engine'} # 添加这行
|
| 13 |
+
if functions:
|
| 14 |
+
for func in functions:
|
| 15 |
+
self.functions[func.__name__] = func
|
| 16 |
+
|
| 17 |
+
def add_function(self, func):
|
| 18 |
+
self.functions[func.__name__] = func
|
| 19 |
+
|
| 20 |
+
def generate_functions_array(self):
|
| 21 |
+
type_mapping = {
|
| 22 |
+
"str": "string",
|
| 23 |
+
"int": "integer",
|
| 24 |
+
"float": "number",
|
| 25 |
+
"bool": "boolean",
|
| 26 |
+
"list": "array",
|
| 27 |
+
"dict": "object"
|
| 28 |
+
}
|
| 29 |
+
functions_array = []
|
| 30 |
+
|
| 31 |
+
for function_name, function in self.functions.items():
|
| 32 |
+
if function_name in self.excluded_functions: # 添加这行
|
| 33 |
+
continue
|
| 34 |
+
# 获取函数的文档字符串和参数列表
|
| 35 |
+
docstring = function.__doc__
|
| 36 |
+
parameters = inspect.signature(function).parameters
|
| 37 |
+
|
| 38 |
+
# 提取函数描述
|
| 39 |
+
docstring_lines = docstring.strip().split(
|
| 40 |
+
'\n') if docstring else []
|
| 41 |
+
function_description = docstring_lines[0].strip(
|
| 42 |
+
) if docstring_lines else ''
|
| 43 |
+
|
| 44 |
+
# 解析参数列表并生成函数描述
|
| 45 |
+
function_info = {
|
| 46 |
+
"name": function_name,
|
| 47 |
+
"description": function_description,
|
| 48 |
+
"parameters": {
|
| 49 |
+
"type": "object",
|
| 50 |
+
"properties": {},
|
| 51 |
+
"required": [] # Add a required field
|
| 52 |
+
}
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
for parameter_name, parameter in parameters.items():
|
| 56 |
+
# 获取参数的注释
|
| 57 |
+
parameter_annotation = parameter.annotation
|
| 58 |
+
if parameter_annotation == inspect.Parameter.empty:
|
| 59 |
+
continue
|
| 60 |
+
|
| 61 |
+
# 如果注解是一个类型,获取它的名字
|
| 62 |
+
# 如果注解是一个字符串,直接使用它
|
| 63 |
+
if isinstance(parameter_annotation, type):
|
| 64 |
+
parameter_annotation_name = parameter_annotation.__name__.lower(
|
| 65 |
+
)
|
| 66 |
+
else:
|
| 67 |
+
parameter_annotation_name = parameter_annotation.lower()
|
| 68 |
+
|
| 69 |
+
# 提取参数描述
|
| 70 |
+
param_description_pattern = rf"{parameter_name}: (.+)"
|
| 71 |
+
param_description_match = [
|
| 72 |
+
re.search(param_description_pattern, line)
|
| 73 |
+
for line in docstring_lines
|
| 74 |
+
]
|
| 75 |
+
param_description = next(
|
| 76 |
+
(match.group(1)
|
| 77 |
+
for match in param_description_match if match), '')
|
| 78 |
+
|
| 79 |
+
# 添加参数描述
|
| 80 |
+
parameter_description = {
|
| 81 |
+
"type":
|
| 82 |
+
type_mapping.get(parameter_annotation_name,
|
| 83 |
+
parameter_annotation_name),
|
| 84 |
+
"description":
|
| 85 |
+
param_description
|
| 86 |
+
}
|
| 87 |
+
function_info["parameters"]["properties"][
|
| 88 |
+
parameter_name] = parameter_description
|
| 89 |
+
|
| 90 |
+
# If the parameter has no default value, add it to the required field.
|
| 91 |
+
if parameter.default == inspect.Parameter.empty:
|
| 92 |
+
function_info["parameters"]["required"].append(
|
| 93 |
+
parameter_name)
|
| 94 |
+
|
| 95 |
+
functions_array.append(function_info)
|
| 96 |
+
|
| 97 |
+
return functions_array
|
| 98 |
+
|
| 99 |
+
async def call_function(self, function_name, args_dict):
|
| 100 |
+
if function_name not in self.functions:
|
| 101 |
+
raise ValueError(f"Function '{function_name}' not found")
|
| 102 |
+
|
| 103 |
+
function = self.functions[function_name]
|
| 104 |
+
# {"role": "function", "name": "get_current_weather", "content": "{\"temperature\": "22", \"unit\": \"celsius\", \"description\": \"Sunny\"}"}
|
| 105 |
+
print(function, args_dict)
|
| 106 |
+
res = await function(**args_dict)
|
| 107 |
+
# 如果返回的内容是元祖或者列表或者字典,那么就返回一个json字符串
|
| 108 |
+
if isinstance(res, (tuple, list, dict)):
|
| 109 |
+
res = json.dumps(res)
|
| 110 |
+
return res
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
# 测试
|
| 114 |
+
def get_current_weather(location: str, unit: str = "celsius"):
|
| 115 |
+
"""
|
| 116 |
+
Get the current weather in a given location.
|
| 117 |
+
|
| 118 |
+
Parameters:
|
| 119 |
+
- location: The city and state, e.g. San Francisco, CA
|
| 120 |
+
- unit: The unit of temperature (celsius or fahrenheit)
|
| 121 |
+
"""
|
| 122 |
+
return {"temperature": "22", "unit": "celsius", "description": "Sunny"}
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
# 定义一个方法来根据传进来的url地址,读取网页的内容
|
| 126 |
+
def get_html(url: str):
|
| 127 |
+
# 定义一个请求头,模拟浏览器访问
|
| 128 |
+
"""
|
| 129 |
+
Get the html content of the url.if user provide the url,then return the html content of the url.
|
| 130 |
+
Parameters:
|
| 131 |
+
url: The url of the website. (required)
|
| 132 |
+
"""
|
| 133 |
+
headers = {
|
| 134 |
+
'User-Agent':
|
| 135 |
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) '
|
| 136 |
+
'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36'
|
| 137 |
+
}
|
| 138 |
+
# 发送请求
|
| 139 |
+
response = requests.get(url, headers=headers)
|
| 140 |
+
# 返回网页内容
|
| 141 |
+
return response.text
|
| 142 |
+
|
| 143 |
+
|
| 144 |
+
def search_by_bard(content: str):
|
| 145 |
+
"""
|
| 146 |
+
Search the content(translate to English language) by bard.if the input content that you don't know how to say, you can use this function.
|
| 147 |
+
Parameters:
|
| 148 |
+
content: The content to search.please change the content language to English.(required)
|
| 149 |
+
"""
|
| 150 |
+
print(content)
|
| 151 |
+
response = openai.ChatCompletion.create(model="bard",
|
| 152 |
+
messages=[{
|
| 153 |
+
'role': 'user',
|
| 154 |
+
'content': content
|
| 155 |
+
}],
|
| 156 |
+
stream=False,
|
| 157 |
+
temperature=0)
|
| 158 |
+
print(response)
|
| 159 |
+
return {'content': response['choices'][0]['message']['content']}
|
| 160 |
+
|
| 161 |
+
|
| 162 |
+
if __name__ == "__main__":
|
| 163 |
+
function_manager = FunctionManager(functions=[search_by_bard])
|
| 164 |
+
functions_array = function_manager.generate_functions_array()
|
| 165 |
+
print(functions_array)
|
| 166 |
+
|
| 167 |
+
# result = function_manager.call_function('get_current_weather', {'location': 'San Francisco, CA', 'unit': 'celsius'})
|
| 168 |
+
# print(result)
|
functions/__init__.py
ADDED
|
File without changes
|
functions/__pycache__/FunctionManager.cpython-39.pyc
ADDED
|
Binary file (4.42 kB). View file
|
|
|
functions/__pycache__/__init__.cpython-39.pyc
ADDED
|
Binary file (198 Bytes). View file
|
|
|
plugins/.DS_Store
ADDED
|
Binary file (6.15 kB). View file
|
|
|
plugins/common/__pycache__/functions.cpython-39.pyc
ADDED
|
Binary file (1.8 kB). View file
|
|
|
plugins/common/config.json
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"enabled": true
|
| 3 |
+
}
|
plugins/common/functions.py
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import chainlit as cl
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
async def need_file_upload():
|
| 6 |
+
"""
|
| 7 |
+
When the user's question mentions handling files, you need to upload files, you can call this function.
|
| 8 |
+
Parameters: None
|
| 9 |
+
"""
|
| 10 |
+
if not os.path.exists('./tmp'):
|
| 11 |
+
os.mkdir('./tmp')
|
| 12 |
+
files = await cl.AskFileMessage(
|
| 13 |
+
content="Please upload a text file to begin!",
|
| 14 |
+
max_size_mb=50,
|
| 15 |
+
accept=[
|
| 16 |
+
"text/plain",
|
| 17 |
+
"image/png",
|
| 18 |
+
"image/jpeg",
|
| 19 |
+
"application/pdf",
|
| 20 |
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", # for .xlsx files
|
| 21 |
+
"application/vnd.ms-excel", # for .xls files
|
| 22 |
+
"text/csv", # for .csv files
|
| 23 |
+
# More MIME types here as needed.
|
| 24 |
+
]).send()
|
| 25 |
+
file = files[0]
|
| 26 |
+
|
| 27 |
+
# 保存文件到paths目录下
|
| 28 |
+
# 判断paths目录是否存在
|
| 29 |
+
file_path = f"./tmp/{file.name}"
|
| 30 |
+
# 保存文件
|
| 31 |
+
content = file.content
|
| 32 |
+
file_name = file.name
|
| 33 |
+
file_type = file.type
|
| 34 |
+
# 保存文件
|
| 35 |
+
# content是bytes类型
|
| 36 |
+
with open(file_path, "wb") as f:
|
| 37 |
+
f.write(content)
|
| 38 |
+
return {
|
| 39 |
+
'type': 'file',
|
| 40 |
+
'path': file_path,
|
| 41 |
+
'name': file_name,
|
| 42 |
+
'file_type': file_type
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
async def show_images(paths: str):
|
| 47 |
+
"""
|
| 48 |
+
If your return contains images in png or jpg format, you can call this function to display the images.
|
| 49 |
+
Parameters: paths: The paths of the images as a comma-separated string.(required)
|
| 50 |
+
"""
|
| 51 |
+
path_list = paths.split(',')
|
| 52 |
+
elments = []
|
| 53 |
+
for i, path in enumerate(path_list):
|
| 54 |
+
tmp_image = cl.Image(name=f"image{i}",
|
| 55 |
+
path=path.strip(),
|
| 56 |
+
display="inline")
|
| 57 |
+
tmp_image.size = "large"
|
| 58 |
+
elments.append(tmp_image)
|
| 59 |
+
|
| 60 |
+
await cl.Message(content="",
|
| 61 |
+
elements=elments).send() # type: ignore
|
| 62 |
+
|
| 63 |
+
return {'description': '图片已经显示成功了,下面的回复中不再需要展示它了'}
|
plugins/python/__pycache__/executor.cpython-39.pyc
ADDED
|
Binary file (2.85 kB). View file
|
|
|
plugins/python/__pycache__/functions.cpython-39.pyc
ADDED
|
Binary file (2.74 kB). View file
|
|
|
plugins/python/config.json
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"enabled": true
|
| 3 |
+
}
|
plugins/python/executor.py
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import abc
|
| 2 |
+
import sys
|
| 3 |
+
import io
|
| 4 |
+
import ast
|
| 5 |
+
import subprocess
|
| 6 |
+
from contextlib import redirect_stdout
|
| 7 |
+
from loguru import logger
|
| 8 |
+
|
| 9 |
+
logger.configure(
|
| 10 |
+
handlers=[
|
| 11 |
+
{
|
| 12 |
+
"sink": sys.stderr,
|
| 13 |
+
"format": "<green>{time}</green> <level>{message}</level>",
|
| 14 |
+
"colorize": True,
|
| 15 |
+
}
|
| 16 |
+
]
|
| 17 |
+
)
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
class Executor(abc.ABC):
|
| 21 |
+
@abc.abstractmethod
|
| 22 |
+
def execute(self, code: str) -> str:
|
| 23 |
+
pass
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
class PythonExecutor(Executor):
|
| 27 |
+
locals = {}
|
| 28 |
+
|
| 29 |
+
def execute(self, code: str) -> str:
|
| 30 |
+
logger.info("Executing Python code: {}", code)
|
| 31 |
+
output = io.StringIO()
|
| 32 |
+
|
| 33 |
+
# Parse the code into an AST.
|
| 34 |
+
tree = ast.parse(code, mode="exec")
|
| 35 |
+
|
| 36 |
+
try:
|
| 37 |
+
# Redirect standard output to our StringIO instance.
|
| 38 |
+
with redirect_stdout(output):
|
| 39 |
+
for node in tree.body:
|
| 40 |
+
# Compile and execute each node.
|
| 41 |
+
exec(
|
| 42 |
+
compile(
|
| 43 |
+
ast.Module(body=[node], type_ignores=[]), "<ast>", "exec"
|
| 44 |
+
),
|
| 45 |
+
None,
|
| 46 |
+
PythonExecutor.locals,
|
| 47 |
+
)
|
| 48 |
+
|
| 49 |
+
# If the node is an expression, print its result.
|
| 50 |
+
if isinstance(node, ast.Expr):
|
| 51 |
+
eval_result = eval(
|
| 52 |
+
compile(ast.Expression(body=node.value), "<ast>", "eval"),
|
| 53 |
+
None,
|
| 54 |
+
PythonExecutor.locals,
|
| 55 |
+
)
|
| 56 |
+
if eval_result is not None:
|
| 57 |
+
print(eval_result)
|
| 58 |
+
except Exception as e:
|
| 59 |
+
logger.error("Error executing Python code: {}", e)
|
| 60 |
+
return str(e)
|
| 61 |
+
|
| 62 |
+
# Retrieve the output and return it.
|
| 63 |
+
return output.getvalue()
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
class CppExecutor(Executor):
|
| 67 |
+
def execute(self, code: str) -> str:
|
| 68 |
+
with open("script.cpp", "w") as f:
|
| 69 |
+
f.write(code)
|
| 70 |
+
try:
|
| 71 |
+
subprocess.run(["g++", "script.cpp"], check=True)
|
| 72 |
+
output = subprocess.run(
|
| 73 |
+
["./a.out"], capture_output=True, text=True, check=True
|
| 74 |
+
)
|
| 75 |
+
return output.stdout
|
| 76 |
+
except subprocess.CalledProcessError as e:
|
| 77 |
+
# Here we include e.stderr in the output.
|
| 78 |
+
raise subprocess.CalledProcessError(e.returncode, e.cmd, output=e.stderr)
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
class RustExecutor(Executor):
|
| 82 |
+
def execute(self, code: str) -> str:
|
| 83 |
+
with open("script.rs", "w") as f:
|
| 84 |
+
f.write(code)
|
| 85 |
+
try:
|
| 86 |
+
subprocess.run(["rustc", "script.rs"], check=True)
|
| 87 |
+
output = subprocess.run(
|
| 88 |
+
["./script"], capture_output=True, text=True, check=True
|
| 89 |
+
)
|
| 90 |
+
return output.stdout
|
| 91 |
+
except subprocess.CalledProcessError as e:
|
| 92 |
+
# Here we include e.stderr in the output.
|
| 93 |
+
raise subprocess.CalledProcessError(e.returncode, e.cmd, output=e.stderr)
|
plugins/python/functions.py
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import asyncio
|
| 2 |
+
import subprocess
|
| 3 |
+
import sys
|
| 4 |
+
import chainlit as cl
|
| 5 |
+
import os
|
| 6 |
+
from .executor import PythonExecutor
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
async def python_exec(code: str, language: str = "python"):
|
| 10 |
+
"""
|
| 11 |
+
Exexute code. \nNote: This endpoint current supports a REPL-like environment for Python only.\n\nArgs:\n request (CodeExecutionRequest): The request object containing the code to execute.\n\nReturns:\n CodeExecutionResponse: The result of the code execution.
|
| 12 |
+
Parameters: code: (str, required): A Python code snippet for execution in a Jupyter environment, where variables and imports from previously executed code are accessible. The code must not rely on external variables/imports not available in this environment, and must print a dictionary `{"type": "<type>", "path": "<path>", "status": "<status>"}` as the last operation. `<type>` can be "image", "file", or "content", `<path>` is the file path (not needed if `<type>` is "content"), `<status>` indicates execution status. Display operations should save output as a file with path returned in the dictionary. If tabular data is generated, it should be directly returned as a string. The code must end with a `print` statement.the end must be print({"type": "<type>", "path": "<path>", "status": "<status>"})
|
| 13 |
+
"""
|
| 14 |
+
|
| 15 |
+
myexcutor = PythonExecutor()
|
| 16 |
+
code_output = myexcutor.execute(code)
|
| 17 |
+
print(f"REPL execution result: {code_output}")
|
| 18 |
+
response = {"result": code_output.strip()}
|
| 19 |
+
return response
|
| 20 |
+
|
| 21 |
+
async def need_install_package(package_name: str) -> dict:
|
| 22 |
+
"""
|
| 23 |
+
If the user's question mentions installing packages, and the packages need to be installed,
|
| 24 |
+
you can call this function.
|
| 25 |
+
Parameters: package_name: The name of the package.(required)
|
| 26 |
+
"""
|
| 27 |
+
# check if package is already installed
|
| 28 |
+
cmd_check = [sys.executable, '-m', 'pip', 'show', package_name]
|
| 29 |
+
proc = subprocess.Popen(cmd_check,
|
| 30 |
+
stdout=subprocess.PIPE,
|
| 31 |
+
stderr=subprocess.PIPE)
|
| 32 |
+
out, _ = proc.communicate()
|
| 33 |
+
if out:
|
| 34 |
+
return {'description': f"{package_name} is already installed"}
|
| 35 |
+
|
| 36 |
+
# install package if it's not installed
|
| 37 |
+
cmd_install = [sys.executable, '-m', 'pip', 'install', package_name]
|
| 38 |
+
process = await asyncio.create_subprocess_exec(
|
| 39 |
+
*cmd_install,
|
| 40 |
+
stdout=asyncio.subprocess.PIPE,
|
| 41 |
+
stderr=asyncio.subprocess.PIPE)
|
| 42 |
+
|
| 43 |
+
stdout, stderr = await process.communicate()
|
| 44 |
+
|
| 45 |
+
if process.returncode != 0:
|
| 46 |
+
await cl.Message(content=f"Failed to install {package_name}.").send()
|
| 47 |
+
return {
|
| 48 |
+
'description':
|
| 49 |
+
f"Error installing {package_name}: {stderr.decode()}"
|
| 50 |
+
}
|
| 51 |
+
await cl.Message(content=f"Successfully installed {package_name}.").send()
|
| 52 |
+
return {'description': f"{package_name} has been successfully installed"}
|
plugins/vue/__pycache__/functions.cpython-39.pyc
ADDED
|
Binary file (3.39 kB). View file
|
|
|
plugins/vue/config.json
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"enabled": true
|
| 3 |
+
}
|
plugins/vue/functions.py
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import subprocess
|
| 2 |
+
|
| 3 |
+
async def vue_install_package(path: str, package_name: str):
|
| 4 |
+
"""
|
| 5 |
+
This function is used to install a package in the Vue project.
|
| 6 |
+
Parameters:
|
| 7 |
+
package_name : The name of the package.
|
| 8 |
+
path : The path of the project.
|
| 9 |
+
"""
|
| 10 |
+
try:
|
| 11 |
+
subprocess.run(["npm", "install", package_name], cwd=path)
|
| 12 |
+
return {
|
| 13 |
+
"status": "true",
|
| 14 |
+
"description": "Package installed successfully.",
|
| 15 |
+
}
|
| 16 |
+
except Exception as e:
|
| 17 |
+
return {"status": "false", "description": str(e)}
|
| 18 |
+
|
| 19 |
+
async def vue_create_directory(path: str, directory_name: str):
|
| 20 |
+
"""
|
| 21 |
+
This function is used to create a directory in the Vue project.
|
| 22 |
+
Parameters:
|
| 23 |
+
path : The path of the project.
|
| 24 |
+
directory_name : The name of the directory.
|
| 25 |
+
"""
|
| 26 |
+
try:
|
| 27 |
+
subprocess.run(["mkdir", directory_name], cwd=path)
|
| 28 |
+
return {
|
| 29 |
+
"status": "true",
|
| 30 |
+
"description": "Directory created successfully.",
|
| 31 |
+
}
|
| 32 |
+
except Exception as e:
|
| 33 |
+
return {"status": "false", "description": str(e)}
|
| 34 |
+
|
| 35 |
+
async def vue_create_file(path: str, file_name: str):
|
| 36 |
+
"""
|
| 37 |
+
This function is used to create a file in the Vue project.
|
| 38 |
+
Parameters:
|
| 39 |
+
path : The path of the project.
|
| 40 |
+
file_name : The name of the file.
|
| 41 |
+
"""
|
| 42 |
+
try:
|
| 43 |
+
subprocess.run(["touch", file_name], cwd=path)
|
| 44 |
+
return {
|
| 45 |
+
"status": "true",
|
| 46 |
+
"description": "File created successfully.",
|
| 47 |
+
}
|
| 48 |
+
except Exception as e:
|
| 49 |
+
return {"status": "false", "description": str(e)}
|
| 50 |
+
|
| 51 |
+
async def vue_get_project_file_list(path: str):
|
| 52 |
+
"""
|
| 53 |
+
This function is used to get the file list of the Vue project.
|
| 54 |
+
Parameters:
|
| 55 |
+
project_name : The name of the project.
|
| 56 |
+
path : The path of the project.
|
| 57 |
+
"""
|
| 58 |
+
# 使用ls命令获取文件列表
|
| 59 |
+
try:
|
| 60 |
+
tree = subprocess.run(["ls", path], capture_output=True)
|
| 61 |
+
return {
|
| 62 |
+
"status": "true",
|
| 63 |
+
"description": tree.stdout.decode(),
|
| 64 |
+
}
|
| 65 |
+
except Exception as e:
|
| 66 |
+
return {"status": "false", "description": str(e)}
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
async def get_vue_project_file_content(path: str, file_name: str):
|
| 70 |
+
"""
|
| 71 |
+
This function is used to get the content of a file in the Vue project.
|
| 72 |
+
Parameters:
|
| 73 |
+
path : The path of the file you want to write to.
|
| 74 |
+
file_name : The name of the file.
|
| 75 |
+
"""
|
| 76 |
+
try:
|
| 77 |
+
with open(f"{path}/{file_name}", "r") as f:
|
| 78 |
+
content = f.read()
|
| 79 |
+
return {
|
| 80 |
+
"status": "true",
|
| 81 |
+
"description": content,
|
| 82 |
+
}
|
| 83 |
+
except Exception as e:
|
| 84 |
+
return {"status": "false", "description": str(e)}
|
| 85 |
+
|
| 86 |
+
async def write_vue_project_file_content(path: str, file_name: str, content: str):
|
| 87 |
+
"""
|
| 88 |
+
This function is used to write content to a file in the Vue project.
|
| 89 |
+
Parameters:
|
| 90 |
+
path : The path of the file you want to write to.
|
| 91 |
+
file_name : The name of the file.
|
| 92 |
+
content : The content to write.
|
| 93 |
+
"""
|
| 94 |
+
try:
|
| 95 |
+
with open(f"{path}/{file_name}", "w") as f:
|
| 96 |
+
f.write(content)
|
| 97 |
+
return {
|
| 98 |
+
"status": "true",
|
| 99 |
+
"description": "File content written successfully.",
|
| 100 |
+
}
|
| 101 |
+
except Exception as e:
|
| 102 |
+
return {"status": "false", "description": str(e)}
|
| 103 |
+
|
requirements.txt
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
chainlit==0.5.2
|
| 2 |
+
loguru==0.5.3
|
| 3 |
+
tiktoken==0.4.0
|
| 4 |
+
prompt_toolkit==3.0.39
|
| 5 |
+
scikit-learn
|
| 6 |
+
pandas
|
| 7 |
+
matplotlib
|
| 8 |
+
numpy
|