darsoarafa commited on
Commit
acfe0e8
·
verified ·
1 Parent(s): ba88fc2

Delete app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -532
app.py DELETED
@@ -1,532 +0,0 @@
1
- from __future__ import annotations as _annotations
2
- import os
3
- import asyncio
4
- import json
5
- import sqlite3
6
- import datetime
7
- import fastapi
8
- import logfire
9
- import time
10
- from collections.abc import AsyncIterator
11
- from concurrent.futures.thread import ThreadPoolExecutor
12
- from contextlib import asynccontextmanager
13
- from dataclasses import dataclass
14
- from datetime import datetime, timezone, date
15
- from functools import partial
16
- from pathlib import Path
17
- from typing import Annotated, Any, Callable, Literal, TypeVar
18
-
19
- from pydantic import BaseModel, Field, ValidationError, model_validator
20
- from typing import List, Optional, Dict
21
-
22
- from fastapi import Depends, Request
23
- from fastapi.responses import FileResponse, Response, StreamingResponse
24
- from typing_extensions import LiteralString, ParamSpec, TypedDict
25
-
26
- from pydantic_ai import Agent
27
- from pydantic_ai.exceptions import UnexpectedModelBehavior
28
- from pydantic_ai.messages import (
29
- ModelMessage,
30
- ModelMessagesTypeAdapter,
31
- ModelRequest,
32
- ModelResponse,
33
- TextPart,
34
- UserPromptPart,
35
- )
36
- from pydantic_ai.models.openai import OpenAIModel
37
-
38
- # Model Local untuk LLM
39
- model = OpenAIModel(
40
- 'gemma-2-2b-it', #'mistral-7b-instruct-v0.3',
41
- base_url='http://localhost:1234/v1', #LM Studio
42
- api_key='your-local-api-key',
43
- )
44
-
45
- # Model Pydantic untuk Sales Order
46
- class product1(BaseModel):
47
- ds_productCode: Optional[str] = "" #str = Field(..., min_length=1, max_length=20)
48
- ds_productName: str = Field(..., min_length=1, max_length=100)
49
- ds_quantity: int = Field(..., ge=1)
50
- ds_unitPrice: float = Field(..., ge=0)
51
- ds_itemAmt: Optional[float] = 0
52
-
53
- # 'if-token-present' means nothing will be sent (and the example will work) if you don't have logfire configured
54
- logfire.configure(send_to_logfire='if-token-present')
55
-
56
- class product(BaseModel):
57
- ds_productCode: Optional[str] = "" #str = Field(..., min_length=1, max_length=20)
58
- ds_productName: Optional[str] = ""
59
- ds_quantity: Optional[int] = 0
60
- ds_unitPrice: Optional[float] = 0
61
- ds_itemAmt: Optional[float] = 0
62
-
63
- class SalesOrder(BaseModel):
64
- ds_salesOrderId: Optional[str] = ""
65
- ds_salesDate: Optional[str] = ""
66
- ds_customerName: str = Field(..., min_length=1, max_length=100)
67
- ds_customerAddress: Optional[str] = ""
68
- ds_items: List[product] = Field(..., min_items=1)
69
- ds_shippingCost:Optional[float] = 0
70
- ds_shippingAddress: Optional[str] = ""
71
- ds_totalAmount:Optional[float] = 0
72
- #ds_paymentTerms: Optional[str] = ""
73
-
74
- #agent= Agent('gemini-1.5-flash', result_type=SalesOrder)
75
-
76
- # # Create a system prompt to guide the model
77
- SYSTEM_PROMPT = """
78
- Anda adalah asisten yang ahli melakukan ekstrak data SalesOrder dari teks user. Format output yang diinginkan hanya berupa JSON saja sesuai class SalesOrder. Tidak usah ada penjelasan lain. Sekali lagi: Output hanya JSON saja. Untuk Nomor Sales Order pasangkan dengan key ds_salesOrderId, untuk Tanggal Sales pasangkan dengan key ds_salesDate, untuk Nama Customer pasangkan dengan Key ds_customerName, untuk Alamat Customer pasangkan dengan key ds_customerAddress, untuk Daftar Item Barang pasangkan dengan key ds_items, untuk Kode Barang pasangkan dengan key ds_productCode, untuk Nama Barang pasangkan dengan key ds_productName, untuk Quantity pasangkan dengan key ds_quantity, untuk Unit Price pasangkan dengan key ds_unitPrice, untuk Total Nilai Per Baris Barang pasangkan dengan key ds_itemAmt, untuk Ongkos Kirim pasangkan dengan key ds_shippingCost, untuk Alamat Pengiriman pasangkan dengan key ds_shippingAddress, untuk Total Nilai Sales Order pasangkan dengan key ds_totalAmount
79
- """
80
- #agent3 = Agent(model=ollama_model, result_type=PetList, retries=3, system_prompt=SYSTEM_PROMPT)
81
- #agent3 = Agent(model=ollama_model, retries=3, system_prompt=SYSTEM_PROMPT)
82
-
83
-
84
- #INI SAJA. SALAH SATU
85
- agent = Agent('gemini-1.5-flash', system_prompt=SYSTEM_PROMPT) # OK-Gemini
86
- #agent = Agent(model, system_prompt=SYSTEM_PROMPT) # OK-Lokal
87
-
88
- THIS_DIR = Path(__file__).parent
89
-
90
-
91
- @asynccontextmanager
92
- async def lifespan(_app: fastapi.FastAPI):
93
- async with Database.connect() as db:
94
- yield {'db': db}
95
-
96
-
97
- app = fastapi.FastAPI(lifespan=lifespan)
98
- logfire.instrument_fastapi(app)
99
-
100
-
101
- @app.get('/')
102
- async def index() -> FileResponse:
103
- return FileResponse((THIS_DIR / 'chat_app.html'), media_type='text/html')
104
-
105
-
106
- @app.get('/chat_app.ts')
107
- async def main_ts() -> FileResponse:
108
- """Get the raw typescript code, it's compiled in the browser, forgive me."""
109
- return FileResponse((THIS_DIR / 'chat_app.ts'), media_type='text/plain')
110
-
111
-
112
- async def get_db(request: Request) -> Database:
113
- return request.state.db
114
-
115
- @app.get('/chat/')
116
- async def get_chat(database: Database = Depends(get_db)) -> Response:
117
- msgs = await database.get_messages()
118
- return Response(
119
- b'\n'.join(json.dumps(to_ds_message(m)).encode('utf-8') for m in msgs),
120
- media_type='text/plain',
121
- )
122
-
123
-
124
-
125
- class ChatMessage(TypedDict):
126
- """Format of messages sent to the browser."""
127
- role: Literal['user', 'model']
128
- timestamp: str
129
- content: str
130
-
131
-
132
- def to_chat_message(m: ModelMessage) -> ChatMessage:
133
- first_part = m.parts[0]
134
- if isinstance(m, ModelRequest):
135
- if isinstance(first_part, UserPromptPart):
136
- return {
137
- 'role': 'user',
138
- 'timestamp': first_part.timestamp.isoformat(),
139
- 'content': first_part.content,
140
- }
141
- elif isinstance(m, ModelResponse):
142
- if isinstance(first_part, TextPart):
143
- return {
144
- 'role': 'model',
145
- 'timestamp': m.timestamp.isoformat(),
146
- 'content': first_part.content,
147
- }
148
- raise UnexpectedModelBehavior(f'Unexpected message type for chat app: {m}')
149
-
150
- def to_ds_message(m: ModelMessage) -> ChatMessage:
151
-
152
- if isinstance(m, ModelRequest):
153
- first_part = m.parts[1]
154
- if isinstance(first_part, UserPromptPart):
155
- return {
156
- 'role': 'user',
157
- 'timestamp': first_part.timestamp.isoformat(),
158
- 'content': first_part.content,
159
- }
160
- elif isinstance(m, ModelResponse):
161
- first_part = m.parts[0]
162
- if isinstance(first_part, TextPart):
163
- return {
164
- 'role': 'model',
165
- 'timestamp': m.timestamp.isoformat(),
166
- 'content': first_part.content,
167
- }
168
- raise UnexpectedModelBehavior(f'Unexpected ds-message type for chat app: {m}')
169
-
170
- def to_form_message(m: ModelMessage) -> ChatMessage:
171
- first_part = m.parts[0]
172
- if isinstance(m, ModelResponse):
173
- if isinstance(first_part, TextPart):
174
- return {
175
- 'role': 'form',
176
- 'timestamp': m.timestamp.isoformat(),
177
- 'content': first_part.content,
178
- }
179
- raise UnexpectedModelBehavior(f'Unexpected message type for chat app: {m}')
180
- @app.post('/chat/')
181
- async def post_chat(
182
- prompt: Annotated[str, fastapi.Form()], database: Database = Depends(get_db)
183
- ) -> StreamingResponse:
184
- async def stream_messages():
185
- """Streams new line delimited JSON `Message`s to the client."""
186
- # stream the user prompt so that can be displayed straight away
187
- yield (
188
- json.dumps(
189
- {
190
- 'role': 'user',
191
- 'timestamp': datetime.now(tz=timezone.utc).isoformat(),
192
- 'content': prompt,
193
- }
194
- ).encode('utf-8')
195
- + b'\n'
196
- )
197
- # get the chat history so far to pass as context to the agent
198
- messages = await database.get_messages()
199
- # run the agent with the user prompt and the chat history
200
- async with agent.run_stream(prompt, message_history=messages) as result:
201
- async for text in result.stream(debounce_by=0.01):
202
- # text here is a `str` and the frontend wants
203
- # JSON encoded ModelResponse, so we create one
204
- m = ModelResponse.from_text(content=text, timestamp=result.timestamp())
205
- yield json.dumps(to_chat_message(m)).encode('utf-8') + b'\n'
206
-
207
- # add new messages (e.g. the user prompt and the agent response in this case) to the database
208
- #print("---",result.new_messages_json(),"---")
209
- #print("***",prompt,"***")
210
- await database.add_messages(result.new_messages_json())
211
- async def ds_messages(prompt1):
212
- #Nama pembeli: Bu Lurah, alamat Bekasi Barat, hari ini membeli Teh Putih dua kaleng harga 110000 per kaleng, juga membeli Teh Hitam 3 kaleng, harga per kaleng 60000. Ongkos kirim ke Bekasi Barat sebesar 36 ribu
213
- #nama pembeli Mas Anang alamat di Jalan Cisitu no.5 Bandung, membeli Chocobar 5 batang harga 15 ribu per batang, dan membeli Rice Cracker 4 buah harga 20 ribu per buah, ongkos kirim ke Jalan Cisitu no.5 sebesar 7 ribu rupiah
214
- try:
215
- #prompt2=f"Ekstrak data Sales Order dari teks: {prompt1}. Format output yang diinginkan hanya berupa JSON saja sesuai class Sales Order. Tidak usah ada penjelasan lain. Sekali lagi: Output hanya JSON saja. Hari ini adalah tanggal {date.today()}. untuk Nomor Sales Order pasangkan dengan key ds_salesOrderId, untuk Tanggal Sales pasangkan dengan key ds_salesDate, untuk Nama Customer pasangkan dengan Key ds_customerName, untuk Alamat Customer pasangkan dengan key ds_customerAddress, untuk Daftar Item Barang pasangkan dengan key ds_items, untuk Kode Barang pasangkan dengan key ds_productCode, untuk Nama Barang pasangkan dengan key ds_productName, untuk Quantity pasangkan dengan key ds_quantity, untuk Unit Price pasangkan dengan key ds_unitPrice, untuk Total Nilai Per Baris Barang pasangkan dengan key ds_itemAmt. Setelah Daftar Item Barang, selanjutnya untuk Ongkos Kirim pasangkan dengan key ds_shippingCost, untuk Alamat Pengiriman pasangkan dengan key ds_shippingAddress, untuk Total Nilai Sales Order pasangkan dengan key ds_totalAmount"
216
- #prompt2=f"Ekstrak data Sales Order dari teks: {prompt1}. Hari ini adalah tanggal {date.today()}"
217
- prompt2=f"{prompt1}. Hari ini adalah tanggal {date.today()}"
218
- yield (
219
- json.dumps(
220
- {
221
- 'role': 'user',
222
- 'timestamp': datetime.now(tz=timezone.utc).isoformat(),
223
- 'content': prompt1,
224
- }
225
- ).encode('utf-8')
226
- + b'\n'
227
- )
228
- #messages = await database.get_messages()
229
- async with agent.run_stream(prompt2) as result:
230
- async for text in result.stream(debounce_by=0.1):
231
- m = ModelResponse.from_text(content=text, timestamp=result.timestamp())
232
- yield json.dumps(to_ds_message(m)).encode('utf-8') + b'\n'
233
-
234
- ##print(result.usage())
235
- #await database.add_messages(result.new_messages_json())
236
- darso = json.loads(result.new_messages_json())
237
- #print(darso)
238
- darso0= darso[0]
239
- #darso0.pop(darso0['parts'][0])
240
- #print("00|------------------")
241
- #print("01|", darso0 )
242
- #print("01a|", darso0['parts'][0] )
243
- #print("01b|", darso0['parts'][1] )
244
- darso0['parts'][0] = darso0['parts'][1]
245
- #print("01?|", darso0 )
246
- #print("01??|", darso )
247
- #print("02|------------------")
248
- darso1= darso[1]
249
- #print("1|", darso1)
250
- darso2= json.loads(json.dumps(darso1))
251
- #print("2|",darso2['parts'][0])
252
- darso3= darso2['parts'][0]
253
- darso4= json.loads(json.dumps(darso3))
254
- #print("4|",darso4['content'])
255
- darso5= darso4['content']
256
- darso5=darso5.split('```', 2)
257
- darso5=darso5[1]
258
- #print("5a|",darso5)
259
- darso5=darso5.replace('json', '')
260
- #print("5|",darso5,"|")
261
- try:
262
- darso6= json.loads(darso5) #json
263
- darso7= SalesOrder.model_validate(darso6)
264
- except:
265
- darso6= "ERR"
266
- #print("6|",darso6,"|")
267
- if "ds_items" in darso5:
268
- cek_str="ds_items"
269
- else:
270
- cek_str="--"
271
- if darso6=="ERR":
272
- ds_id = time.time()
273
- ds_salesOrderId = "ERR"
274
- ds_salesDate = 'ERR'
275
- ds_customerName="-"
276
- ds_customerAddress="-"
277
-
278
- ds_productName1 = "Produk1 --- "
279
- ds_quantity1 = 1
280
- ds_unitPrice1 = 0
281
- ds_itemAmt1 = 0
282
-
283
- ds_productName2 = "Produk2 --- "
284
- ds_quantity2 = 0
285
- ds_unitPrice2 = 0
286
- ds_itemAmt2 = 0
287
-
288
- ds_productName3 = "Produk3 --- "
289
- ds_quantity3 = 0
290
- ds_unitPrice3 = 0
291
- ds_itemAmt3 = 0
292
- ds_shippingAddress=""
293
- ds_shippingCost=0
294
- ds_totalAmount=0
295
- else:
296
- ds_id = time.time()
297
- ds_salesOrderId = "OK"
298
- ds_salesDate = 'OK'
299
- try:
300
- ds_salesOrderId = darso7.ds_salesOrderId
301
- #print("7|ds_salesOrderId")
302
- ds_salesDate = darso7.ds_salesDate
303
- #print("7|ds_salesDate")
304
- ds_customerName=f"""{darso7.ds_customerName}"""
305
- #print("7|ds_customerName:",ds_customerName)
306
- ds_customerAddress=f"""{darso7.ds_customerAddress}"""
307
- #print("7|ds_customerAddress:", len(darso7.ds_items))
308
- ds_productName1 = darso7.ds_items[0].ds_productName
309
- #print("7|ds_productName1")
310
- ds_quantity1 = darso7.ds_items[0].ds_quantity
311
- #print("7|ds_quantity1")
312
- ds_unitPrice1 = darso7.ds_items[0].ds_unitPrice
313
- #print("7|ds_unitPrice1")
314
- ds_itemAmt1 = darso7.ds_items[0].ds_itemAmt
315
- #print("7|ds_itemAmt1")
316
- ds_productName2 = "-"
317
- ds_quantity2 = 0
318
- ds_unitPrice2 = 0
319
- ds_itemAmt2 = 0
320
- ds_productName3 = "-"
321
- ds_quantity3 = 0
322
- ds_unitPrice3 = 0
323
- ds_itemAmt3 = 0
324
-
325
- if len(darso7.ds_items)>1:
326
- ds_productName2 = darso7.ds_items[1].ds_productName
327
- ds_quantity2 = darso7.ds_items[1].ds_quantity
328
- ds_unitPrice2 = darso7.ds_items[1].ds_unitPrice
329
- ds_itemAmt2 = darso7.ds_items[1].ds_itemAmt
330
- if len(darso7.ds_items)>2:
331
- ds_productName3 = darso7.ds_items[2].ds_productName
332
- ds_quantity3 = darso7.ds_items[2].ds_quantity
333
- ds_unitPrice3 = darso7.ds_items[2].ds_unitPrice
334
- ds_itemAmt3 = darso7.ds_items[2].ds_itemAmt
335
-
336
- ds_shippingCost=darso7.ds_shippingCost
337
- #print("7|ds_shippingCost")
338
- ds_shippingAddress=f"""{darso7.ds_shippingAddress}"""
339
- #print("7|ds_shippingAddress")
340
- ds_totalAmount=darso7.ds_totalAmount
341
- #print("7|ds_totalAmount")
342
- except:
343
- ds_salesOrderId = "OK2"
344
- ds_salesDate = 'OK2'
345
- ds_customerName="-"
346
- ds_customerAddress="-"
347
-
348
- ds_productName1 = "Produk1"
349
- ds_quantity1 = 0
350
- ds_unitPrice1 = 0
351
- ds_itemAmt1 = 0
352
-
353
- ds_productName2 = "Produk2"
354
- ds_quantity2 = 0
355
- ds_unitPrice2 = 0
356
- ds_itemAmt2 = 0
357
-
358
- ds_productName3 = "Produk3"
359
- ds_quantity3 = 0
360
- ds_unitPrice3 = 0
361
- ds_itemAmt3 = 0
362
- ds_shippingAddress=""
363
- ds_shippingCost=0
364
- ds_totalAmount=0
365
-
366
- formDs = f"""
367
-
368
- <form id="myaiForm{ds_id}" action="javascript:abcde({ds_id});" class="form-container">
369
- <h3>Pesanan</h3>
370
- <table>
371
- <tr>
372
- <td><label for="ds_salesOrderId"><b>SO#</b></label><input type="text" placeholder="" name="ds_salesOrderId" value="{ds_salesOrderId}"></td>
373
- <td><label for="ds_salesDate"><b>Date</b></label><input type="text" placeholder="" name="ds_salesDate" value="{ds_salesDate}"></td>
374
- </tr>
375
- <tr>
376
- <td colspan="2"><label for="ds_customerName"><b>Customer</b></label><input type="text" placeholder="" name="ds_customerName" value="{ds_customerName}"></td>
377
- </tr>
378
- <tr>
379
- <td colspan="2"><label for="ds_customerAddress"><b>Alamat</b></label><input type="text" placeholder="" name="ds_customerAddress" value="{ds_customerAddress}"></td>
380
- </tr>
381
- </table style="width:100%">
382
- <b>Item Barang:</b>
383
- <table>
384
- <tr><th>Prod</th><th style="text-align: center;">Qty</th><th style="text-align: center;">Prc</th><th style="text-align: center;">Rp</th></tr>
385
- <tr>
386
- <td><input type="text" placeholder="-" name="ds_productName1" value="{ds_productName1}"></td>
387
- <td><input type="text" style="text-align: center;" name="ds_quantity1" value={ds_quantity1}></td>
388
- <td><input type="text" style="text-align: center;" name="ds_unitPrice1" value={ds_unitPrice1}></td>
389
- <td><input type="text" style="text-align: center;" name="ds_itemAmt1" value={ds_itemAmt1}></td>
390
- </tr>
391
- <tr>
392
- <td><input type="text" placeholder="-" name="ds_productName2" value="{ds_productName2}"></td>
393
- <td><input type="text" style="text-align: center;" name="ds_quantity2" value={ds_quantity2}></td>
394
- <td><input type="text" style="text-align: center;" name="ds_unitPrice2" value={ds_unitPrice2}></td>
395
- <td><input type="text" style="text-align: center;" name="ds_itemAmt2" value={ds_itemAmt2}></td>
396
- </tr>
397
- <tr>
398
- <td><input type="text" placeholder="-" name="ds_productName3" value="{ds_productName3}"></td>
399
- <td><input type="text" style="text-align: center;" name="ds_quantity3" value={ds_quantity3}></td>
400
- <td><input type="text" style="text-align: center;" name="ds_unitPrice3" value={ds_unitPrice3}></td>
401
- <td><input type="text" style="text-align: center;" name="ds_itemAmt3" value={ds_itemAmt3}></td>
402
- </tr>
403
- </table>
404
- <table>
405
- <tr>
406
- <td style="text-align: center;"><b>Ongkir</b></td>
407
- <td style="text-align: center;"><b>Total</b></td>
408
- </tr>
409
- <tr>
410
- <td><input type="text" style="text-align: center;" placeholder="0" name="ds_shippingCost" value={ds_shippingCost}></td>
411
- <td><input type="text" style="text-align: center;" placeholder="0" name="ds_totalAmount" value={ds_totalAmount}></td>
412
- </tr>
413
- <tr>
414
- <td colspan="2"><label for="ds_shippingAddress"><b></b></label><input type="text" placeholder="" name="ds_shippingAddress" value="{ds_shippingAddress}"></td>
415
- </tr>
416
- </table>
417
- <button type="submit" class="btn">Submit</button>
418
- <button type="button" class="btn cancel" onclick="closeAiForm({ds_id})">Close</button>
419
- </form>
420
- <form id="myaiForm2{ds_id}" class="form-container" style="display:none;">
421
- <button type="button" class="btn umum" onclick="openAiForm({ds_id})">Open Form</button>
422
- </form>
423
- """
424
- m = ModelResponse.from_text(content=formDs, timestamp=result.timestamp())
425
- yield json.dumps(to_ds_message(m)).encode('utf-8') + b'\n'
426
- print("OK")
427
- #await database.add_messages(result.new_messages_json())
428
- await database.add_messages(json.dumps(darso))
429
- ##print(len(items))
430
- #darso7 = SalesOrder.model_validate(darso6)
431
- #print("[--",darso7.ds_customerName,"--]")
432
- #darso8 = darso7.ds_items[0]
433
- ##, len(darso7.ds_items)
434
- #print("[--",darso8.ds_productName,"--]")
435
- except ValueError as e:
436
- print(e)
437
- if prompt[0] == "@" :
438
- #print("@@@", prompt, "@@@")
439
- nn = len(prompt)
440
- prompt = prompt[1:nn]
441
- print(">>>", prompt, "<<<")
442
- return StreamingResponse(ds_messages(prompt), media_type='text/plain')
443
- elif prompt[0] != "@" :
444
- #print("biasa")
445
- return StreamingResponse(ds_messages(prompt), media_type='text/plain')
446
- print("** selesai **")
447
- return StreamingResponse(ds_messages(prompt), media_type='text/plain')
448
-
449
- P = ParamSpec('P')
450
- R = TypeVar('R')
451
-
452
-
453
- @dataclass
454
- class Database:
455
- """Rudimentary database to store chat messages in SQLite.
456
-
457
- The SQLite standard library package is synchronous, so we
458
- use a thread pool executor to run queries asynchronously.
459
- """
460
-
461
- con: sqlite3.Connection
462
- _loop: asyncio.AbstractEventLoop
463
- _executor: ThreadPoolExecutor
464
-
465
- @classmethod
466
- @asynccontextmanager
467
- async def connect(
468
- cls, file: Path = THIS_DIR / '.chat_messages.sqlite'
469
- ) -> AsyncIterator[Database]:
470
- with logfire.span('connect to DB'):
471
- loop = asyncio.get_event_loop()
472
- executor = ThreadPoolExecutor(max_workers=1)
473
- con = await loop.run_in_executor(executor, cls._connect, file)
474
- slf = cls(con, loop, executor)
475
- try:
476
- yield slf
477
- finally:
478
- await slf._asyncify(con.close)
479
-
480
- @staticmethod
481
- def _connect(file: Path) -> sqlite3.Connection:
482
- con = sqlite3.connect(str(file))
483
- con = logfire.instrument_sqlite3(con)
484
- cur = con.cursor()
485
- cur.execute(
486
- 'CREATE TABLE IF NOT EXISTS messages (id INT PRIMARY KEY, message_list TEXT);'
487
- )
488
- con.commit()
489
- return con
490
-
491
- async def add_messages(self, messages: bytes):
492
- await self._asyncify(
493
- self._execute,
494
- 'INSERT INTO messages (message_list) VALUES (?);',
495
- messages,
496
- commit=True,
497
- )
498
- await self._asyncify(self.con.commit)
499
-
500
- async def get_messages(self) -> list[ModelMessage]:
501
- c = await self._asyncify(
502
- self._execute, 'SELECT message_list FROM messages order by id asc'
503
- )
504
- rows = await self._asyncify(c.fetchall)
505
- messages: list[ModelMessage] = []
506
- for row in rows:
507
- messages.extend(ModelMessagesTypeAdapter.validate_json(row[0]))
508
- return messages
509
-
510
- def _execute(
511
- self, sql: LiteralString, *args: Any, commit: bool = False
512
- ) -> sqlite3.Cursor:
513
- cur = self.con.cursor()
514
- cur.execute(sql, args)
515
- if commit:
516
- self.con.commit()
517
- return cur
518
-
519
- async def _asyncify(
520
- self, func: Callable[P, R], *args: P.args, **kwargs: P.kwargs
521
- ) -> R:
522
- return await self._loop.run_in_executor( # type: ignore
523
- self._executor,
524
- partial(func, **kwargs),
525
- *args, # type: ignore
526
- )
527
-
528
- if __name__ == '__main__':
529
- import uvicorn
530
- uvicorn.run(
531
- 'app:app', reload=True, host="0.0.0.0", port=7860, reload_dirs=[str(THIS_DIR)]
532
- )