Skip to content
This repository was archived by the owner on Mar 26, 2025. It is now read-only.

Commit a1cb686

Browse files
authored
Merge pull request #104 from openchatai/falta/patch-ci
Falta/patch ci
2 parents 1e59641 + 3757280 commit a1cb686

File tree

12 files changed

+202
-215
lines changed

12 files changed

+202
-215
lines changed

.github/workflows/build-widget.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ jobs:
1414
with:
1515
node-version: 18
1616

17+
- name: install pnpm
18+
run: npm install -g pnpm
19+
1720
- name: Install dependencies
1821
run: cd copilot-widget/ && pnpm install
1922

llm-server/.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,4 +148,5 @@ cython_debug/
148148
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
149149
# and can be added to the global gitignore or merged into this file. For a more nuclear
150150
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
151-
.idea/
151+
.idea/
152+
.env.local

llm-server/app.py

Lines changed: 8 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,108 +1,29 @@
11
import logging
2-
import requests
3-
import traceback
42

5-
from flask import Flask, request
6-
from langchain.chains.openai_functions import create_structured_output_chain
7-
from langchain.chat_models import ChatOpenAI
8-
from langchain.prompts import ChatPromptTemplate
9-
10-
from langchain.utilities.openapi import OpenAPISpec
11-
from utils.base import try_to_match_and_call_api_endpoint
12-
from models.models import AiResponseFormat
3+
from flask import Flask, request, jsonify, Response
134
from routes.workflow.workflow_controller import workflow
14-
from routes.swagger_controller.swagger_api import swagger_workflow
15-
import json
5+
from routes._swagger.controller import _swagger
166
from typing import Any, Tuple
17-
from prompts.base import api_base_prompt, non_api_base_prompt
18-
from routes.workflow.workflow_service import run_workflow
19-
from routes.workflow.typings.run_workflow_input import WorkflowData
20-
from utils.detect_multiple_intents import hasSingleIntent, hasMultipleIntents
21-
import os
22-
from dotenv import load_dotenv
23-
247

25-
load_dotenv()
26-
shared_folder = os.getenv("SHARED_FOLDER", "/app/shared_data/")
278
logging.basicConfig(level=logging.DEBUG)
289

2910

3011
app = Flask(__name__)
3112

3213
app.register_blueprint(workflow, url_prefix="/workflow")
33-
app.register_blueprint(swagger_workflow, url_prefix="/swagger_api")
14+
app.register_blueprint(_swagger, url_prefix="/swagger_api")
15+
from routes.root_service import handle_request
3416

3517

3618
## TODO: Implement caching for the swagger file content (no need to load it everytime)
3719
@app.route("/handle", methods=["POST", "OPTIONS"])
38-
def handle():
20+
def handle() -> Response:
3921
data = request.get_json()
40-
text = data.get("text")
41-
swagger_url = data.get("swagger_url")
42-
base_prompt = data.get("base_prompt")
43-
headers = data.get("headers", {})
44-
server_base_url = data.get("server_base_url")
45-
46-
if not base_prompt:
47-
return json.dumps({"error": "base_prompt is required"}), 400
48-
49-
if not text:
50-
return json.dumps({"error": "text is required"}), 400
51-
52-
if not swagger_url:
53-
return json.dumps({"error": "swagger_url is required"}), 400
54-
55-
if swagger_url.startswith("https://"):
56-
pass
57-
else:
58-
swagger_url = shared_folder + swagger_url
59-
60-
print(f"swagger_url::{swagger_url}")
61-
try:
62-
if hasMultipleIntents(text):
63-
result = run_workflow(
64-
WorkflowData(text, swagger_url, headers, server_base_url)
65-
)
66-
67-
return result
68-
except Exception as e:
69-
raise e
70-
71-
if swagger_url.startswith("https://"):
72-
response = requests.get(swagger_url)
73-
if response.status_code == 200:
74-
swagger_text = response.text
75-
else:
76-
return json.dumps({"error": "Failed to fetch Swagger content"}), 500
77-
else:
78-
try:
79-
with open(swagger_url, "r") as file:
80-
swagger_text = file.read()
81-
except FileNotFoundError:
82-
return json.dumps({"error": "File not found"}), 404
83-
84-
swagger_spec = OpenAPISpec.from_text(swagger_text)
85-
8622
try:
87-
json_output = try_to_match_and_call_api_endpoint(swagger_spec, text, headers)
23+
response = handle_request(data)
24+
return jsonify(response)
8825
except Exception as e:
89-
logging.error(f"Failed to call or map API endpoint: {str(e)}")
90-
logging.error("Exception traceback:\n" + traceback.format_exc())
91-
json_output = None
92-
93-
llm = ChatOpenAI(model="gpt-3.5-turbo-0613", temperature=0)
94-
95-
if json_output is None:
96-
prompt_msgs = non_api_base_prompt(base_prompt, text)
97-
98-
else:
99-
prompt_msgs = api_base_prompt(base_prompt, text, json_output)
100-
101-
prompt = ChatPromptTemplate(messages=prompt_msgs)
102-
chain = create_structured_output_chain(AiResponseFormat, llm, prompt, verbose=False)
103-
chain_output = chain.run(question=text)
104-
105-
return json.loads(json.dumps(chain_output.dict())), 200
26+
return jsonify({"error": str(e)})
10627

10728

10829
@app.errorhandler(500)
Lines changed: 21 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
11
from flask import Flask, request, jsonify, Blueprint, request, Response
2-
from flask_pymongo import PyMongo
32

43
import json, yaml
54
from bson import ObjectId
5+
import routes._swagger.service as swagger_service
66

77
from utils.db import Database
8-
from typing import Any
9-
import requests
108

119
db_instance = Database()
1210
mongo = db_instance.get_db()
13-
swagger_workflow = Blueprint("swagger_workflow", __name__)
11+
_swagger = Blueprint("_swagger", __name__)
1412

1513

16-
@swagger_workflow.route("/", methods=["GET"])
17-
def get_swagger_files() -> Response:
14+
@_swagger.route("/b/<id>", methods=["GET"])
15+
def get_swagger_files(id: str) -> Response:
1816
# Get page and page_size query params
1917
page = int(request.args.get("page", 1))
2018
page_size = int(request.args.get("page_size", 10))
@@ -26,7 +24,7 @@ def get_swagger_files() -> Response:
2624
# Query for paginated docs
2725
files = [
2826
doc.update({"_id": str(doc["_id"])}) or doc
29-
for doc in mongo.swagger_files.find({}, {}).skip(skip).limit(limit)
27+
for doc in mongo.swagger_files.find({"bot_id": id}, {}).skip(skip).limit(limit)
3028
]
3129

3230
# Get total docs count
@@ -38,56 +36,23 @@ def get_swagger_files() -> Response:
3836
return jsonify(data)
3937

4038

41-
@swagger_workflow.route("/", methods=["POST"])
42-
def add_swagger_file():
43-
if request.content_type == "application/json":
44-
# JSON file
45-
file_content = request.get_json()
46-
47-
elif "multipart/form-data" in request.content_type:
48-
# Uploaded file
49-
file = request.files.get("file")
50-
if file is None:
51-
return jsonify({"error": "File upload is required"}), 400
52-
53-
if file.filename.endswith(".json"):
54-
try:
55-
file_content = json.load(file)
56-
except json.JSONDecodeError as e:
57-
return (
58-
jsonify({"error": "Invalid JSON format in the uploaded file"}),
59-
400,
60-
)
61-
62-
elif file.filename.endswith(".yaml") or file.filename.endswith(".yml"):
63-
try:
64-
file_content = yaml.safe_load(file)
65-
except yaml.YAMLError as e:
66-
return (
67-
jsonify({"error": "Invalid YAML format in the uploaded file"}),
68-
400,
69-
)
70-
71-
else:
72-
return jsonify({"error": "Unsupported content type"}), 400
73-
74-
# Insert into MongoDB
75-
mongo.swagger_files.insert_one(file_content)
76-
77-
return jsonify({"message": "File added successfully"})
78-
79-
80-
@swagger_workflow.route("/<id>", methods=["GET"])
81-
def get_swagger_file(id: str) -> Response:
82-
file = mongo.swagger_files.find_one({"_id": ObjectId(id)})
39+
@_swagger.route("/b/<id>", methods=["POST"])
40+
def add_swagger_file(id) -> Response:
41+
result = swagger_service.add_swagger_file(request, id)
42+
return jsonify(result)
43+
44+
45+
@_swagger.route("/<_id>", methods=["GET"])
46+
def get_swagger_file(_id: str) -> Response:
47+
file = mongo.swagger_files.find_one({"_id": ObjectId(_id)})
8348
if not file:
8449
return jsonify({"message": "Swagger file not found"})
8550

8651
file["_id"] = str(file["_id"])
8752
return jsonify(file)
8853

8954

90-
@swagger_workflow.route("/transform/<_id>", methods=["GET"])
55+
@_swagger.route("/transform/<_id>", methods=["GET"])
9156
def get_transformed_swagger_file(_id: str) -> Response:
9257
swagger_json = mongo.swagger_files.aggregate(
9358
[
@@ -138,18 +103,18 @@ def get_transformed_swagger_file(_id: str) -> Response:
138103
return jsonify(list(swagger_json))
139104

140105

141-
@swagger_workflow.route("/<id>", methods=["PUT"])
142-
def update_swagger_file(id: str) -> Response:
106+
@_swagger.route("/<_id>", methods=["PUT"])
107+
def update_swagger_file(_id: str) -> Response:
143108
data = request.get_json()
144-
result = mongo.swagger_files.update_one({"_id": ObjectId(id)}, {"$set": data})
109+
result = mongo.swagger_files.update_one({"_id": ObjectId(_id)}, {"$set": data})
145110
if result.modified_count == 1:
146111
return jsonify({"message": "Swagger file updated successfully"})
147112
return jsonify({"message": "Swagger file not found"})
148113

149114

150-
@swagger_workflow.route("/<id>", methods=["DELETE"])
151-
def delete_swagger_file(id: str) -> Response:
152-
result = mongo.swagger_files.delete_one({"_id": ObjectId(id)})
115+
@_swagger.route("/<_id>", methods=["DELETE"])
116+
def delete_swagger_file(_id: str) -> Response:
117+
result = mongo.swagger_files.delete_one({"_id": ObjectId(_id)})
153118
if result.deleted_count == 1:
154119
return jsonify({"message": "Swagger file deleted successfully"})
155120
return jsonify({"message": "Swagger file not found"})
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import json
2+
import yaml
3+
4+
from utils.db import Database
5+
6+
db_instance = Database()
7+
mongo = db_instance.get_db()
8+
from typing import Dict
9+
from flask import Request
10+
11+
12+
def add_swagger_file(request: Request, id: str) -> Dict[str, str]:
13+
if request.content_type == "application/json":
14+
# JSON file
15+
file_content = request.get_json()
16+
17+
elif "multipart/form-data" in request.content_type:
18+
# Uploaded file
19+
file = request.files.get("file")
20+
if file is None:
21+
return {"error": "File upload is required"}
22+
23+
if file.filename and file.filename.endswith(".json"):
24+
try:
25+
file_content = json.load(file)
26+
except json.JSONDecodeError as e:
27+
return {"error": "Invalid JSON format in uploaded file"}
28+
29+
elif file.filename and (
30+
file.filename.endswith(".yaml") or file.filename.endswith(".yml")
31+
):
32+
try:
33+
file_content = yaml.safe_load(file)
34+
except yaml.YAMLError as e:
35+
return {"error": "Invalid YAML format in uploaded file"}
36+
37+
else:
38+
return {"error": "Unsupported content type"}
39+
40+
# Insert into MongoDB
41+
file_content["bot_id"] = id
42+
mongo.swagger_files.insert_one(file_content)
43+
44+
return {"message": "File added successfully"}

0 commit comments

Comments
 (0)