Spaces:
Sleeping
Sleeping
Commit ·
a0d7d94
1
Parent(s): a0f95e7
Uploaded three AI FAQ bot
Browse files- .gitignore +5 -0
- app.py +5 -0
- data/GetCustomers.json +95 -0
- data/GetRealTimeCommissions.json +66 -0
- data/GetVolumes.json +213 -0
- data_service.py +55 -0
- generate_service.py +203 -0
- interface.py +121 -0
- requirements.txt +0 -0
.gitignore
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.env
|
| 2 |
+
.idea
|
| 3 |
+
.vscode
|
| 4 |
+
__pycache__
|
| 5 |
+
*.pyc
|
app.py
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
from interface import demo
|
| 3 |
+
|
| 4 |
+
if __name__ == "__main__":
|
| 5 |
+
demo.launch(server_name="0.0.0.0", server_port=7860, inbrowser=True)
|
data/GetCustomers.json
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"customers": [
|
| 3 |
+
{
|
| 4 |
+
"customerID": 451930,
|
| 5 |
+
"firstName": "Test",
|
| 6 |
+
"lastName": "Test",
|
| 7 |
+
"company": "",
|
| 8 |
+
"customerType": 3,
|
| 9 |
+
"customerStatus": 1,
|
| 10 |
+
"email": "testtest@gmail.com",
|
| 11 |
+
"phone": "8011111111",
|
| 12 |
+
"phone2": "",
|
| 13 |
+
"mobilePhone": "",
|
| 14 |
+
"fax": "",
|
| 15 |
+
"mainAddress1": "test1",
|
| 16 |
+
"mainAddress2": "test",
|
| 17 |
+
"mainCity": "test",
|
| 18 |
+
"mainState": "JHR",
|
| 19 |
+
"mainZip": "93000",
|
| 20 |
+
"mainCountry": "MY",
|
| 21 |
+
"mainCounty": "Utah",
|
| 22 |
+
"mailAddress1": "1441 Innovation Way",
|
| 23 |
+
"mailAddress2": "",
|
| 24 |
+
"mailCity": "Lehi",
|
| 25 |
+
"mailState": "JHR",
|
| 26 |
+
"mailZip": "84043",
|
| 27 |
+
"mailCountry": "MY",
|
| 28 |
+
"mailCounty": "Utah",
|
| 29 |
+
"otherAddress1": "1441 Innovation Way",
|
| 30 |
+
"otherAddress2": "",
|
| 31 |
+
"otherCity": "Lehi",
|
| 32 |
+
"otherState": "JHR",
|
| 33 |
+
"otherZip": "84043",
|
| 34 |
+
"otherCountry": "MY",
|
| 35 |
+
"otherCounty": "UT",
|
| 36 |
+
"loginName": "IvoryTest",
|
| 37 |
+
"enrollerID": 1,
|
| 38 |
+
"sponsorID": 0,
|
| 39 |
+
"rankID": 40,
|
| 40 |
+
"birthDate": "1987-01-03T00:00:00",
|
| 41 |
+
"field1": "",
|
| 42 |
+
"field2": "",
|
| 43 |
+
"field3": "",
|
| 44 |
+
"field4": "",
|
| 45 |
+
"field5": "",
|
| 46 |
+
"field6": "",
|
| 47 |
+
"field7": "0",
|
| 48 |
+
"field8": "",
|
| 49 |
+
"field9": "",
|
| 50 |
+
"field10": "0",
|
| 51 |
+
"field11": "1",
|
| 52 |
+
"field12": "2026-01-01 12:00:00",
|
| 53 |
+
"field13": "",
|
| 54 |
+
"field14": "",
|
| 55 |
+
"field15": "",
|
| 56 |
+
"date1": "2020-11-02T11:45:24",
|
| 57 |
+
"date2": "2023-02-16T20:48:20",
|
| 58 |
+
"date3": null,
|
| 59 |
+
"date4": null,
|
| 60 |
+
"date5": null,
|
| 61 |
+
"currencyCode": "myr",
|
| 62 |
+
"payableToName": "",
|
| 63 |
+
"defaultWarehouseID": 11,
|
| 64 |
+
"payableType": 8,
|
| 65 |
+
"checkThreshold": 0.0000,
|
| 66 |
+
"priceType": 3,
|
| 67 |
+
"languageID": 0,
|
| 68 |
+
"gender": 0,
|
| 69 |
+
"salesTaxID": "",
|
| 70 |
+
"vatRegistration": "",
|
| 71 |
+
"isSalesTaxExempt": false,
|
| 72 |
+
"isSubscribedToBroadcasts": true,
|
| 73 |
+
"createdDate": "2020-11-02T10:43:24",
|
| 74 |
+
"modifiedDate": "2025-10-21T16:21:05.843",
|
| 75 |
+
"middleName": "",
|
| 76 |
+
"nameSuffix": "",
|
| 77 |
+
"mainAddress3": "",
|
| 78 |
+
"mailAddress3": "",
|
| 79 |
+
"otherAddress3": "",
|
| 80 |
+
"binaryPlacementPreference": 11,
|
| 81 |
+
"useBinaryHoldingTank": false,
|
| 82 |
+
"mainAddressVerified": false,
|
| 83 |
+
"mailAddressVerified": false,
|
| 84 |
+
"otherAddressVerified": false,
|
| 85 |
+
"customerKey": null,
|
| 86 |
+
"enrollerKey": null,
|
| 87 |
+
"sponsorKey": null,
|
| 88 |
+
"payableTyID": 8,
|
| 89 |
+
"canLogin": true,
|
| 90 |
+
"genderID": "U",
|
| 91 |
+
"genderDescription": "Unspecified"
|
| 92 |
+
}
|
| 93 |
+
],
|
| 94 |
+
"recordCount": 1
|
| 95 |
+
}
|
data/GetRealTimeCommissions.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"commissions": [
|
| 3 |
+
{
|
| 4 |
+
"customerID": 451930,
|
| 5 |
+
"periodType": 1,
|
| 6 |
+
"periodID": 377,
|
| 7 |
+
"periodDescription": "Week 139 10/13-10/19",
|
| 8 |
+
"currencyCode": "usd",
|
| 9 |
+
"commissionTotal": 42758.1575,
|
| 10 |
+
"bonuses": [
|
| 11 |
+
{
|
| 12 |
+
"description": "Team Commissions",
|
| 13 |
+
"amount": 22500.0000,
|
| 14 |
+
"bonusID": 26
|
| 15 |
+
},
|
| 16 |
+
{
|
| 17 |
+
"description": "Leadership Matching Bonus",
|
| 18 |
+
"amount": 16334.5000,
|
| 19 |
+
"bonusID": 27
|
| 20 |
+
},
|
| 21 |
+
{
|
| 22 |
+
"description": "Global Leadership Pool Bonus (GLPB)",
|
| 23 |
+
"amount": 3417.1916,
|
| 24 |
+
"bonusID": 28
|
| 25 |
+
},
|
| 26 |
+
{
|
| 27 |
+
"description": "Founders Pool Bonus (FPB)",
|
| 28 |
+
"amount": 506.4659,
|
| 29 |
+
"bonusID": 29
|
| 30 |
+
}
|
| 31 |
+
],
|
| 32 |
+
"customerKey": null
|
| 33 |
+
},
|
| 34 |
+
{
|
| 35 |
+
"customerID": 451930,
|
| 36 |
+
"periodType": 1,
|
| 37 |
+
"periodID": 378,
|
| 38 |
+
"periodDescription": "Week 140 10/20-10/26",
|
| 39 |
+
"currencyCode": "usd",
|
| 40 |
+
"commissionTotal": 35335.7143,
|
| 41 |
+
"bonuses": [
|
| 42 |
+
{
|
| 43 |
+
"description": "Team Commissions",
|
| 44 |
+
"amount": 20385.0000,
|
| 45 |
+
"bonusID": 26
|
| 46 |
+
},
|
| 47 |
+
{
|
| 48 |
+
"description": "Leadership Matching Bonus",
|
| 49 |
+
"amount": 12906.2500,
|
| 50 |
+
"bonusID": 27
|
| 51 |
+
},
|
| 52 |
+
{
|
| 53 |
+
"description": "Global Leadership Pool Bonus (GLPB)",
|
| 54 |
+
"amount": 1854.4252,
|
| 55 |
+
"bonusID": 28
|
| 56 |
+
},
|
| 57 |
+
{
|
| 58 |
+
"description": "Founders Pool Bonus (FPB)",
|
| 59 |
+
"amount": 190.0391,
|
| 60 |
+
"bonusID": 29
|
| 61 |
+
}
|
| 62 |
+
],
|
| 63 |
+
"customerKey": null
|
| 64 |
+
}
|
| 65 |
+
]
|
| 66 |
+
}
|
data/GetVolumes.json
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"volumes": [
|
| 3 |
+
{
|
| 4 |
+
"customerID": 451930,
|
| 5 |
+
"periodType": 1,
|
| 6 |
+
"periodID": 364,
|
| 7 |
+
"periodDescription": "Week 126 7/14-7/20",
|
| 8 |
+
"volume1": 1.0000,
|
| 9 |
+
"volume2": 0.0000,
|
| 10 |
+
"volume3": -250.0000,
|
| 11 |
+
"volume4": 1315.0000,
|
| 12 |
+
"volume5": 2485.0000,
|
| 13 |
+
"volume6": 0.0000,
|
| 14 |
+
"volume7": 58.0000,
|
| 15 |
+
"volume8": 1.0000,
|
| 16 |
+
"volume9": 59.0000,
|
| 17 |
+
"volume10": 0.0000,
|
| 18 |
+
"volume11": 18.0000,
|
| 19 |
+
"volume12": 1.0000,
|
| 20 |
+
"volume13": 0.0000,
|
| 21 |
+
"volume14": 1.0000,
|
| 22 |
+
"volume15": 0.0000,
|
| 23 |
+
"volume16": 2145.0000,
|
| 24 |
+
"volume17": 0.0000,
|
| 25 |
+
"volume18": 180.0000,
|
| 26 |
+
"volume19": 1565.0000,
|
| 27 |
+
"volume20": 510.0000,
|
| 28 |
+
"volume21": 2454.0000,
|
| 29 |
+
"volume22": 3254.0000,
|
| 30 |
+
"volume23": 4594.0000,
|
| 31 |
+
"volume24": 1.0000,
|
| 32 |
+
"volume25": 0.0000,
|
| 33 |
+
"volume26": 0.0000,
|
| 34 |
+
"volume27": 0.0000,
|
| 35 |
+
"volume28": 0.0000,
|
| 36 |
+
"volume29": 0.0000,
|
| 37 |
+
"volume30": 0.0000,
|
| 38 |
+
"volume31": 7236.0000,
|
| 39 |
+
"volume32": 740.0000,
|
| 40 |
+
"volume33": 760.0000,
|
| 41 |
+
"volume34": 0.0000,
|
| 42 |
+
"volume35": 6000.0000,
|
| 43 |
+
"volume36": 84.0000,
|
| 44 |
+
"volume37": 6760.0000,
|
| 45 |
+
"volume38": 84.0000,
|
| 46 |
+
"volume39": 6000.0000,
|
| 47 |
+
"volume40": 84.0000,
|
| 48 |
+
"volume41": 2314.0000,
|
| 49 |
+
"volume42": 300.0000,
|
| 50 |
+
"volume43": 3014.0000,
|
| 51 |
+
"volume44": 400.0000,
|
| 52 |
+
"volume45": 4114.0000,
|
| 53 |
+
"volume46": 640.0000,
|
| 54 |
+
"volume47": 6760.0000,
|
| 55 |
+
"volume48": 84.0000,
|
| 56 |
+
"volume49": 0.0000,
|
| 57 |
+
"volume50": 0.0000,
|
| 58 |
+
"volume51": 6760.0000,
|
| 59 |
+
"volume52": 84.0000,
|
| 60 |
+
"volume53": 0.0000,
|
| 61 |
+
"volume54": 0.0000,
|
| 62 |
+
"volume55": 84.0000,
|
| 63 |
+
"volume56": 6760.0000,
|
| 64 |
+
"volume57": 0.0000,
|
| 65 |
+
"volume58": 1.0000,
|
| 66 |
+
"volume59": 1.0000,
|
| 67 |
+
"volume60": 0.0000,
|
| 68 |
+
"volume61": 1.0000,
|
| 69 |
+
"volume62": 0.0000,
|
| 70 |
+
"volume63": 0.0000,
|
| 71 |
+
"volume64": 1.0000,
|
| 72 |
+
"volume65": 1.0000,
|
| 73 |
+
"volume66": 0.0000,
|
| 74 |
+
"volume67": 0.0000,
|
| 75 |
+
"volume68": 0.0000,
|
| 76 |
+
"volume69": 510.0000,
|
| 77 |
+
"volume70": 0.0000,
|
| 78 |
+
"volume71": 0.0000,
|
| 79 |
+
"volume72": 0.0000,
|
| 80 |
+
"volume73": 0.0000,
|
| 81 |
+
"volume74": 0.0000,
|
| 82 |
+
"volume75": 40.0000,
|
| 83 |
+
"volume76": 40.0000,
|
| 84 |
+
"volume77": 40.0000,
|
| 85 |
+
"volume78": 40.0000,
|
| 86 |
+
"volume79": 40.0000,
|
| 87 |
+
"volume80": 40.0000,
|
| 88 |
+
"volume81": 0.0000,
|
| 89 |
+
"volume82": 40.0000,
|
| 90 |
+
"volume83": 1.0000,
|
| 91 |
+
"volume84": 830.0000,
|
| 92 |
+
"volume85": 0.0000,
|
| 93 |
+
"volume86": 1.0000,
|
| 94 |
+
"volume87": 0.0000,
|
| 95 |
+
"volume88": 0.0000,
|
| 96 |
+
"volume89": 0.0000,
|
| 97 |
+
"volume90": 0.0000,
|
| 98 |
+
"volume91": 2.0000,
|
| 99 |
+
"volume92": 0.0000,
|
| 100 |
+
"volume93": 0.0000,
|
| 101 |
+
"volume94": 0.0000,
|
| 102 |
+
"volume95": 31.0000,
|
| 103 |
+
"volume96": 0.0000,
|
| 104 |
+
"volume97": 0.0000,
|
| 105 |
+
"volume98": 0.0000,
|
| 106 |
+
"volume99": 0.0000,
|
| 107 |
+
"volume100": 0.0000,
|
| 108 |
+
"rankID": 40,
|
| 109 |
+
"paidRankID": 40,
|
| 110 |
+
"volume101": 390.0000,
|
| 111 |
+
"volume102": 390.0000,
|
| 112 |
+
"volume103": 0.0000,
|
| 113 |
+
"volume104": 2205.0000,
|
| 114 |
+
"volume105": 1.0000,
|
| 115 |
+
"volume106": 0.0000,
|
| 116 |
+
"volume107": -250.0000,
|
| 117 |
+
"volume108": 0.0000,
|
| 118 |
+
"volume109": 9.0000,
|
| 119 |
+
"volume110": 0.0000,
|
| 120 |
+
"volume111": 0.0000,
|
| 121 |
+
"volume112": 1.0000,
|
| 122 |
+
"volume113": 61.0000,
|
| 123 |
+
"volume114": 6.0000,
|
| 124 |
+
"volume115": 5.0000,
|
| 125 |
+
"volume116": 0.0000,
|
| 126 |
+
"volume117": 67.0000,
|
| 127 |
+
"volume118": 0.0000,
|
| 128 |
+
"volume119": 0.0000,
|
| 129 |
+
"volume120": 5.0000,
|
| 130 |
+
"volume121": 1860.0000,
|
| 131 |
+
"volume122": 0.0000,
|
| 132 |
+
"volume123": 0.0000,
|
| 133 |
+
"volume124": 1535.0000,
|
| 134 |
+
"volume125": 0.0000,
|
| 135 |
+
"volume126": 0.0000,
|
| 136 |
+
"volume127": 0.0000,
|
| 137 |
+
"volume128": 1535.0000,
|
| 138 |
+
"volume129": 74200.0000,
|
| 139 |
+
"volume130": 200.0000,
|
| 140 |
+
"volume131": 0.0000,
|
| 141 |
+
"volume132": 1430.0000,
|
| 142 |
+
"volume133": 0.0000,
|
| 143 |
+
"volume134": 0.0000,
|
| 144 |
+
"volume135": 0.0000,
|
| 145 |
+
"volume136": 2915.0000,
|
| 146 |
+
"volume137": 0.0000,
|
| 147 |
+
"volume138": 0.0000,
|
| 148 |
+
"volume139": 0.0000,
|
| 149 |
+
"volume140": 0.0000,
|
| 150 |
+
"volume141": 0.0000,
|
| 151 |
+
"volume142": 0.0000,
|
| 152 |
+
"volume143": 10111.0000,
|
| 153 |
+
"volume144": 0.0000,
|
| 154 |
+
"volume145": 0.0000,
|
| 155 |
+
"volume146": 0.0000,
|
| 156 |
+
"volume147": 0.0000,
|
| 157 |
+
"volume148": 0.0000,
|
| 158 |
+
"volume149": 0.0000,
|
| 159 |
+
"volume150": 0.0000,
|
| 160 |
+
"volume151": 830.0000,
|
| 161 |
+
"volume152": 740.0000,
|
| 162 |
+
"volume153": 4.0000,
|
| 163 |
+
"volume154": 0.0000,
|
| 164 |
+
"volume155": 830.0000,
|
| 165 |
+
"volume156": 830.0000,
|
| 166 |
+
"volume157": 0.0000,
|
| 167 |
+
"volume158": 0.0000,
|
| 168 |
+
"volume159": 125.0000,
|
| 169 |
+
"volume160": 830.0000,
|
| 170 |
+
"volume161": 0.0000,
|
| 171 |
+
"volume162": 0.0000,
|
| 172 |
+
"volume163": 0.0000,
|
| 173 |
+
"volume164": 0.0000,
|
| 174 |
+
"volume165": 0.0000,
|
| 175 |
+
"volume166": 0.0000,
|
| 176 |
+
"volume167": 2288.0000,
|
| 177 |
+
"volume168": 7.0000,
|
| 178 |
+
"volume169": 0.0000,
|
| 179 |
+
"volume170": 0.0000,
|
| 180 |
+
"volume171": 0.0000,
|
| 181 |
+
"volume172": 0.0000,
|
| 182 |
+
"volume173": 2265.0000,
|
| 183 |
+
"volume174": 240.0000,
|
| 184 |
+
"volume175": 240.0000,
|
| 185 |
+
"volume176": 130.0000,
|
| 186 |
+
"volume177": 130.0000,
|
| 187 |
+
"volume178": 0.0000,
|
| 188 |
+
"volume179": 110.0000,
|
| 189 |
+
"volume180": 240.0000,
|
| 190 |
+
"volume181": 240.0000,
|
| 191 |
+
"volume182": 240.0000,
|
| 192 |
+
"volume183": 0.0000,
|
| 193 |
+
"volume184": 0.0000,
|
| 194 |
+
"volume185": 0.0000,
|
| 195 |
+
"volume186": 0.0000,
|
| 196 |
+
"volume187": 0.0000,
|
| 197 |
+
"volume188": 0.0000,
|
| 198 |
+
"volume189": 0.0000,
|
| 199 |
+
"volume190": 3220.0000,
|
| 200 |
+
"volume191": 2265.0000,
|
| 201 |
+
"volume192": 2265.0000,
|
| 202 |
+
"volume193": 2265.0000,
|
| 203 |
+
"volume194": 650.0000,
|
| 204 |
+
"volume195": 3.0000,
|
| 205 |
+
"volume196": 2485.0000,
|
| 206 |
+
"volume197": 0.0000,
|
| 207 |
+
"volume198": 0.0000,
|
| 208 |
+
"volume199": 1315.0000,
|
| 209 |
+
"volume200": 0.0000,
|
| 210 |
+
"customerKey": null
|
| 211 |
+
}
|
| 212 |
+
]
|
| 213 |
+
}
|
data_service.py
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json
|
| 2 |
+
import os
|
| 3 |
+
from pathlib import Path
|
| 4 |
+
from typing import Dict, Any, Optional
|
| 5 |
+
import logging
|
| 6 |
+
|
| 7 |
+
logging.basicConfig(level=logging.INFO)
|
| 8 |
+
logger = logging.getLogger(__name__)
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
class DataService:
|
| 12 |
+
def __init__(self, data_dir: str = "data"):
|
| 13 |
+
"""
|
| 14 |
+
Initialize data service.
|
| 15 |
+
|
| 16 |
+
Args:
|
| 17 |
+
data_dir: Path to data directory (default: "data")
|
| 18 |
+
"""
|
| 19 |
+
self.data_dir = Path(data_dir)
|
| 20 |
+
|
| 21 |
+
if not self.data_dir.exists():
|
| 22 |
+
raise ValueError(f"Data directory '{data_dir}' does not exist")
|
| 23 |
+
|
| 24 |
+
logger.info(f"DataService initialized with directory: {self.data_dir}")
|
| 25 |
+
|
| 26 |
+
def get_data(self, filename: str) -> Optional[Dict[str, Any]]:
|
| 27 |
+
"""
|
| 28 |
+
Read and return complete data from JSON file.
|
| 29 |
+
|
| 30 |
+
Args:
|
| 31 |
+
filename: Name of JSON file (e.g., "GetCustomers.json")
|
| 32 |
+
|
| 33 |
+
Returns:
|
| 34 |
+
Dictionary with complete JSON data or None if error
|
| 35 |
+
"""
|
| 36 |
+
file_path = self.data_dir / filename
|
| 37 |
+
|
| 38 |
+
try:
|
| 39 |
+
if not file_path.exists():
|
| 40 |
+
logger.error(f"File not found: {file_path}")
|
| 41 |
+
return None
|
| 42 |
+
|
| 43 |
+
with open(file_path, 'r', encoding='utf-8') as f:
|
| 44 |
+
data = json.load(f)
|
| 45 |
+
|
| 46 |
+
logger.info(f"Successfully loaded data from {filename}")
|
| 47 |
+
return data
|
| 48 |
+
|
| 49 |
+
except json.JSONDecodeError as e:
|
| 50 |
+
logger.error(f"Invalid JSON in {filename}: {e}")
|
| 51 |
+
return None
|
| 52 |
+
except Exception as e:
|
| 53 |
+
logger.error(f"Error reading {filename}: {e}")
|
| 54 |
+
return None
|
| 55 |
+
|
generate_service.py
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import logging
|
| 3 |
+
import json
|
| 4 |
+
from openai import OpenAI
|
| 5 |
+
from dotenv import load_dotenv
|
| 6 |
+
from data_service import DataService
|
| 7 |
+
|
| 8 |
+
# Load environment variables from .env file
|
| 9 |
+
load_dotenv(override=True)
|
| 10 |
+
|
| 11 |
+
# Configure logging
|
| 12 |
+
logging.basicConfig(
|
| 13 |
+
level=logging.INFO,
|
| 14 |
+
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
| 15 |
+
)
|
| 16 |
+
logger = logging.getLogger(__name__)
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
class OpenAIService:
|
| 20 |
+
def __init__(self, api_key=None, assistant_id=None, data_dir="data"):
|
| 21 |
+
"""
|
| 22 |
+
Initialize OpenAI service with Assistant API.
|
| 23 |
+
|
| 24 |
+
Args:
|
| 25 |
+
api_key: OpenAI API key (defaults to OPENAI_API_KEY env var)
|
| 26 |
+
assistant_id: OpenAI Assistant ID (defaults to ASSISTANT_ID env var)
|
| 27 |
+
data_dir: Path to data directory for DataService (default: "data")
|
| 28 |
+
"""
|
| 29 |
+
logger.info("Initializing OpenAI service...")
|
| 30 |
+
|
| 31 |
+
self.api_key = api_key or os.getenv("OPENAI_API_KEY")
|
| 32 |
+
self.assistant_id = assistant_id or os.getenv("ASSISTANT_ID")
|
| 33 |
+
|
| 34 |
+
if not self.api_key:
|
| 35 |
+
logger.error("OpenAI API key not found in environment variables")
|
| 36 |
+
raise ValueError("OpenAI API key is required. Set OPENAI_API_KEY environment variable.")
|
| 37 |
+
if not self.assistant_id:
|
| 38 |
+
logger.error("Assistant ID not found in environment variables")
|
| 39 |
+
raise ValueError("Assistant ID is required. Set ASSISTANT_ID environment variable.")
|
| 40 |
+
|
| 41 |
+
logger.info(f"API key loaded (length: {len(self.api_key)})")
|
| 42 |
+
logger.info(f"Assistant ID: {self.assistant_id}")
|
| 43 |
+
|
| 44 |
+
self.client = OpenAI(api_key=self.api_key)
|
| 45 |
+
self.thread = None
|
| 46 |
+
self.data_service = DataService(data_dir)
|
| 47 |
+
|
| 48 |
+
logger.info("OpenAI service initialized successfully")
|
| 49 |
+
|
| 50 |
+
def create_thread(self):
|
| 51 |
+
"""Create a new conversation thread."""
|
| 52 |
+
logger.info("Creating new conversation thread...")
|
| 53 |
+
self.thread = self.client.beta.threads.create()
|
| 54 |
+
logger.info(f"Thread created successfully: {self.thread.id}")
|
| 55 |
+
return self.thread.id
|
| 56 |
+
|
| 57 |
+
def get_or_create_thread(self):
|
| 58 |
+
"""Get existing thread or create a new one."""
|
| 59 |
+
if not self.thread:
|
| 60 |
+
logger.info("No existing thread found, creating new thread")
|
| 61 |
+
self.create_thread()
|
| 62 |
+
else:
|
| 63 |
+
logger.info(f"Using existing thread: {self.thread.id}")
|
| 64 |
+
return self.thread.id
|
| 65 |
+
|
| 66 |
+
def execute_tool_call(self, tool_name, tool_arguments):
|
| 67 |
+
"""
|
| 68 |
+
Execute a tool call and return the result.
|
| 69 |
+
|
| 70 |
+
Args:
|
| 71 |
+
tool_name: Name of the tool to execute
|
| 72 |
+
tool_arguments: Dictionary of arguments for the tool
|
| 73 |
+
|
| 74 |
+
Returns:
|
| 75 |
+
str: JSON string with the tool execution result in format { success: bool, result/error: data }
|
| 76 |
+
"""
|
| 77 |
+
logger.info(f"Executing tool: {tool_name} with arguments: {tool_arguments}")
|
| 78 |
+
|
| 79 |
+
try:
|
| 80 |
+
if tool_name == "get_real_time_commissions":
|
| 81 |
+
result = self.data_service.get_data("GetRealTimeCommissions.json")
|
| 82 |
+
if result is None:
|
| 83 |
+
return json.dumps({"success": False, "error": f"Failed to load data from GetRealTimeCommissions.json"})
|
| 84 |
+
|
| 85 |
+
return json.dumps({"success": True, "result": result})
|
| 86 |
+
elif tool_name == "get_volumes":
|
| 87 |
+
result = self.data_service.get_data("GetVolumes.json")
|
| 88 |
+
if result is None:
|
| 89 |
+
return json.dumps({"success": False, "error": f"Failed to load data from GetVolumes.json"})
|
| 90 |
+
|
| 91 |
+
return json.dumps({"success": True, "result": result})
|
| 92 |
+
elif tool_name == "get_customers":
|
| 93 |
+
result = self.data_service.get_data("GetCustomers.json")
|
| 94 |
+
if result is None:
|
| 95 |
+
return json.dumps({"success": False, "error": f"Failed to load data from GetCustomers.json"})
|
| 96 |
+
|
| 97 |
+
return json.dumps({"success": True, "result": result})
|
| 98 |
+
else:
|
| 99 |
+
logger.warning(f"Unknown tool: {tool_name}")
|
| 100 |
+
return json.dumps({"success": False, "error": f"Unknown tool: {tool_name}"})
|
| 101 |
+
|
| 102 |
+
except Exception as e:
|
| 103 |
+
logger.error(f"Error executing tool {tool_name}: {str(e)}", exc_info=True)
|
| 104 |
+
return json.dumps({"success": False, "error": str(e)})
|
| 105 |
+
|
| 106 |
+
def generate_stream(self, message):
|
| 107 |
+
"""
|
| 108 |
+
Generate response from assistant with streaming and tool handling.
|
| 109 |
+
|
| 110 |
+
Args:
|
| 111 |
+
message: User's message string
|
| 112 |
+
|
| 113 |
+
Yields:
|
| 114 |
+
str: Chunks of the response as they arrive
|
| 115 |
+
"""
|
| 116 |
+
try:
|
| 117 |
+
logger.info(f"Processing message: {message[:50]}...")
|
| 118 |
+
thread_id = self.get_or_create_thread()
|
| 119 |
+
|
| 120 |
+
# Add user message to thread
|
| 121 |
+
logger.info(f"Adding message to thread {thread_id}")
|
| 122 |
+
self.client.beta.threads.messages.create(
|
| 123 |
+
thread_id=thread_id,
|
| 124 |
+
role="user",
|
| 125 |
+
content=message
|
| 126 |
+
)
|
| 127 |
+
logger.info("Message added successfully")
|
| 128 |
+
|
| 129 |
+
# Stream the assistant's response
|
| 130 |
+
logger.info("Starting assistant response stream...")
|
| 131 |
+
chunk_count = 0
|
| 132 |
+
skipped_annotations = 0
|
| 133 |
+
|
| 134 |
+
with self.client.beta.threads.runs.stream(
|
| 135 |
+
thread_id=thread_id,
|
| 136 |
+
assistant_id=self.assistant_id
|
| 137 |
+
) as stream:
|
| 138 |
+
for event in stream:
|
| 139 |
+
# Handle text streaming
|
| 140 |
+
if event.event == "thread.message.delta":
|
| 141 |
+
for content in event.data.delta.content:
|
| 142 |
+
if hasattr(content, 'text') and hasattr(content.text, 'value'):
|
| 143 |
+
if hasattr(content.text, 'annotations') and content.text.annotations:
|
| 144 |
+
skipped_annotations += 1
|
| 145 |
+
continue
|
| 146 |
+
|
| 147 |
+
chunk_count += 1
|
| 148 |
+
yield content.text.value
|
| 149 |
+
|
| 150 |
+
# Handle tool calls
|
| 151 |
+
elif event.event == "thread.run.requires_action":
|
| 152 |
+
logger.info("Assistant requires action (tool calls)")
|
| 153 |
+
run_id = event.data.id
|
| 154 |
+
tool_calls = event.data.required_action.submit_tool_outputs.tool_calls
|
| 155 |
+
|
| 156 |
+
tool_outputs = []
|
| 157 |
+
for tool_call in tool_calls:
|
| 158 |
+
logger.info(f"Processing tool call: {tool_call.function.name}")
|
| 159 |
+
|
| 160 |
+
tool_arguments = json.loads(tool_call.function.arguments)
|
| 161 |
+
tool_output = self.execute_tool_call(
|
| 162 |
+
tool_call.function.name,
|
| 163 |
+
tool_arguments
|
| 164 |
+
)
|
| 165 |
+
|
| 166 |
+
tool_outputs.append({
|
| 167 |
+
"tool_call_id": tool_call.id,
|
| 168 |
+
"output": tool_output
|
| 169 |
+
})
|
| 170 |
+
|
| 171 |
+
# Submit tool outputs and continue streaming
|
| 172 |
+
logger.info(f"Submitting {len(tool_outputs)} tool outputs")
|
| 173 |
+
with self.client.beta.threads.runs.submit_tool_outputs_stream(
|
| 174 |
+
thread_id=thread_id,
|
| 175 |
+
run_id=run_id,
|
| 176 |
+
tool_outputs=tool_outputs
|
| 177 |
+
) as tool_stream:
|
| 178 |
+
for tool_event in tool_stream:
|
| 179 |
+
if tool_event.event == "thread.message.delta":
|
| 180 |
+
for content in tool_event.data.delta.content:
|
| 181 |
+
if hasattr(content, 'text') and hasattr(content.text, 'value'):
|
| 182 |
+
if hasattr(content.text, 'annotations') and content.text.annotations:
|
| 183 |
+
skipped_annotations += 1
|
| 184 |
+
continue
|
| 185 |
+
|
| 186 |
+
chunk_count += 1
|
| 187 |
+
yield content.text.value
|
| 188 |
+
|
| 189 |
+
logger.info(f"Stream completed. Chunks received: {chunk_count}, Annotations skipped: {skipped_annotations}")
|
| 190 |
+
|
| 191 |
+
except Exception as e:
|
| 192 |
+
logger.error(f"Error in generate_stream: {str(e)}", exc_info=True)
|
| 193 |
+
yield f"Error: {str(e)}"
|
| 194 |
+
|
| 195 |
+
def clear_thread(self):
|
| 196 |
+
"""Clear the current thread by creating a new one."""
|
| 197 |
+
if self.thread:
|
| 198 |
+
logger.info(f"Clearing thread: {self.thread.id}")
|
| 199 |
+
else:
|
| 200 |
+
logger.info("No active thread to clear")
|
| 201 |
+
self.thread = None
|
| 202 |
+
logger.info("Thread cleared. New thread will be created on next message")
|
| 203 |
+
|
interface.py
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
from generate_service import OpenAIService
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
# Initialize OpenAI service
|
| 6 |
+
openai_service = OpenAIService()
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
def respond(message, history):
|
| 10 |
+
"""
|
| 11 |
+
Process user message and stream the response from OpenAI Assistant.
|
| 12 |
+
|
| 13 |
+
Args:
|
| 14 |
+
message: User's input message
|
| 15 |
+
history: Chat history as list of tuples
|
| 16 |
+
|
| 17 |
+
Yields:
|
| 18 |
+
Updated history with streaming response
|
| 19 |
+
"""
|
| 20 |
+
if not message.strip():
|
| 21 |
+
return
|
| 22 |
+
|
| 23 |
+
# Add user message to history with loading indicator
|
| 24 |
+
history.append((message, '<span class="loading-dots">🤔 Thinking<span style="animation: blink 1.4s infinite; animation-delay: 0s;">.</span><span style="animation: blink 1.4s infinite; animation-delay: 0.2s;">.</span><span style="animation: blink 1.4s infinite; animation-delay: 0.4s;">.</span></span>'))
|
| 25 |
+
yield history, ""
|
| 26 |
+
|
| 27 |
+
# Stream the assistant's response
|
| 28 |
+
response_text = ""
|
| 29 |
+
first_chunk = True
|
| 30 |
+
for chunk in openai_service.generate_stream(message):
|
| 31 |
+
response_text += chunk
|
| 32 |
+
# Replace loading message with actual response
|
| 33 |
+
history[-1] = (message, response_text)
|
| 34 |
+
yield history, ""
|
| 35 |
+
first_chunk = False
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
def clear_chat():
|
| 39 |
+
"""Clear the chat history and create a new thread."""
|
| 40 |
+
openai_service.clear_thread()
|
| 41 |
+
return []
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
with gr.Blocks(css="""
|
| 45 |
+
#chatbot-container {
|
| 46 |
+
height: calc(100vh - 200px) !important;
|
| 47 |
+
min-height: 600px;
|
| 48 |
+
}
|
| 49 |
+
#input-row {
|
| 50 |
+
position: sticky;
|
| 51 |
+
bottom: 0;
|
| 52 |
+
background: white;
|
| 53 |
+
padding: 10px 0;
|
| 54 |
+
}
|
| 55 |
+
.contain {
|
| 56 |
+
max-width: 100% !important;
|
| 57 |
+
padding: 0 !important;
|
| 58 |
+
}
|
| 59 |
+
#clear-btn {
|
| 60 |
+
position: absolute;
|
| 61 |
+
right: 10px;
|
| 62 |
+
top: 10px;
|
| 63 |
+
z-index: 100;
|
| 64 |
+
}
|
| 65 |
+
@keyframes blink {
|
| 66 |
+
0%, 100% { opacity: 1; }
|
| 67 |
+
50% { opacity: 0.3; }
|
| 68 |
+
}
|
| 69 |
+
.message.bot:has(.loading-dots) {
|
| 70 |
+
animation: pulse 1.5s ease-in-out infinite;
|
| 71 |
+
}
|
| 72 |
+
@keyframes pulse {
|
| 73 |
+
0%, 100% { opacity: 1; }
|
| 74 |
+
50% { opacity: 0.6; }
|
| 75 |
+
}
|
| 76 |
+
""") as demo:
|
| 77 |
+
|
| 78 |
+
with gr.Row():
|
| 79 |
+
gr.Markdown("# Chat Interface")
|
| 80 |
+
clear_button = gr.Button("Clear", elem_id="clear-btn", size="sm")
|
| 81 |
+
|
| 82 |
+
chatbot = gr.Chatbot(
|
| 83 |
+
value=[],
|
| 84 |
+
elem_id="chatbot-container",
|
| 85 |
+
height="calc(100vh - 200px)",
|
| 86 |
+
show_label=False,
|
| 87 |
+
sanitize_html=False,
|
| 88 |
+
)
|
| 89 |
+
|
| 90 |
+
with gr.Row(elem_id="input-row"):
|
| 91 |
+
with gr.Column(scale=9):
|
| 92 |
+
msg_input = gr.Textbox(
|
| 93 |
+
placeholder="Type your message here...",
|
| 94 |
+
show_label=False,
|
| 95 |
+
container=False
|
| 96 |
+
)
|
| 97 |
+
with gr.Column(scale=1, min_width=100):
|
| 98 |
+
send_button = gr.Button("Send", variant="primary")
|
| 99 |
+
|
| 100 |
+
# Event handlers
|
| 101 |
+
msg_input.submit(
|
| 102 |
+
respond,
|
| 103 |
+
inputs=[msg_input, chatbot],
|
| 104 |
+
outputs=[chatbot, msg_input]
|
| 105 |
+
)
|
| 106 |
+
|
| 107 |
+
send_button.click(
|
| 108 |
+
respond,
|
| 109 |
+
inputs=[msg_input, chatbot],
|
| 110 |
+
outputs=[chatbot, msg_input]
|
| 111 |
+
)
|
| 112 |
+
|
| 113 |
+
clear_button.click(
|
| 114 |
+
clear_chat,
|
| 115 |
+
inputs=None,
|
| 116 |
+
outputs=chatbot
|
| 117 |
+
)
|
| 118 |
+
|
| 119 |
+
|
| 120 |
+
if __name__ == "__main__":
|
| 121 |
+
demo.launch(inbrowser=True)
|
requirements.txt
ADDED
|
Binary file (2.47 kB). View file
|
|
|