Compare commits
24
Commits
15b93e3cfb
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
29471a61f4 | ||
|
|
47f8f231aa | ||
|
|
95ededec5a | ||
|
|
f2357ae2ac | ||
|
|
ff9d1ae170 | ||
|
|
16f96316c0 | ||
|
|
69e40a89fe | ||
|
|
61073f4772 | ||
|
|
bf3d86ad2c | ||
|
|
470239ec9f | ||
|
|
dd27f2506e | ||
|
|
13253b2802 | ||
|
|
9cc3a486c1 | ||
|
|
d2ad277066 | ||
|
|
bcb4bbc197 | ||
|
|
923bc09c14 | ||
|
|
e57a395dd4 | ||
|
|
b9d20b4a3d | ||
|
|
2ec22695f8 | ||
|
|
1d1ff6b1da | ||
|
|
6f41dd00dc | ||
|
|
b62aff7d3a | ||
|
|
114a22267b | ||
|
|
ffcbd65514 |
+2
-1
@@ -1,3 +1,4 @@
|
|||||||
.venv
|
.venv
|
||||||
__*
|
__pycache__
|
||||||
.pypirc
|
.pypirc
|
||||||
|
.history
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
PYTHON=.venv/bin/python
|
||||||
|
PIP=.venv/bin/pip
|
||||||
|
|
||||||
|
all: build
|
||||||
|
|
||||||
|
ensure_env:
|
||||||
|
-@python3 -m venv .venv
|
||||||
|
|
||||||
|
build: ensure_env
|
||||||
|
$(PIP) install -e .
|
||||||
|
$(PIP) install build
|
||||||
|
$(PIP) install shed
|
||||||
|
$(PYTHON) -m shed
|
||||||
|
$(PYTHON) -m build
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -20,12 +20,15 @@ yura ws://[host]:[port]/[path]/
|
|||||||
## Python
|
## Python
|
||||||
```python
|
```python
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
from yura.client import AsyncClient
|
from yura.client import AsyncClient
|
||||||
|
|
||||||
|
|
||||||
async def communicate():
|
async def communicate():
|
||||||
client = AsyncClient("ws://[host]:[port]/[path]/")
|
client = AsyncClient("ws://[host]:[port]/[path]/")
|
||||||
async for response in client.chat("Your prompt"):
|
async for response in client.chat("Your prompt"):
|
||||||
print(response)
|
print(response)
|
||||||
|
|
||||||
|
|
||||||
asyncio.run(communicate())
|
asyncio.run(communicate())
|
||||||
```
|
```
|
||||||
|
|||||||
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
@@ -1,14 +1,16 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import pathlib
|
|
||||||
import os
|
import os
|
||||||
|
import pathlib
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
args = sys.argv[1:]
|
args = sys.argv[1:]
|
||||||
args_string = " ".join(args)
|
args_string = " ".join(args)
|
||||||
|
|
||||||
|
|
||||||
def install():
|
def install():
|
||||||
os.system("./.venv/bin/python -m pip install -e .")
|
os.system("./.venv/bin/python -m pip install -e .")
|
||||||
|
|
||||||
|
|
||||||
def build():
|
def build():
|
||||||
os.system("./.venv/bin/python -m pip install build")
|
os.system("./.venv/bin/python -m pip install build")
|
||||||
os.system("rm -r dist")
|
os.system("rm -r dist")
|
||||||
@@ -17,7 +19,6 @@ def build():
|
|||||||
os.system("./.venv/bin/python -m black .")
|
os.system("./.venv/bin/python -m black .")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if not pathlib.Path(".venv").exists():
|
if not pathlib.Path(".venv").exists():
|
||||||
os.system("python3 -m venv .venv")
|
os.system("python3 -m venv .venv")
|
||||||
install()
|
install()
|
||||||
@@ -35,4 +36,3 @@ if "publish" in sys.argv:
|
|||||||
|
|
||||||
if "run" in sys.argv:
|
if "run" in sys.argv:
|
||||||
os.system("./.venv/bin/yura " + args_string)
|
os.system("./.venv/bin/yura " + args_string)
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[metadata]
|
[metadata]
|
||||||
name = yura
|
name = yura
|
||||||
version = 14.3.9
|
version = 14.4.5
|
||||||
description = Yura async AI client
|
description = Yura async AI client
|
||||||
author = retoor
|
author = retoor
|
||||||
author_email = retoor@retoor.io
|
author_email = retoor@retoor.io
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
Metadata-Version: 2.1
|
Metadata-Version: 2.1
|
||||||
Name: yura
|
Name: yura
|
||||||
Version: 14.3.9
|
Version: 14.4.5
|
||||||
Summary: Yura async AI client
|
Summary: Yura async AI client
|
||||||
Author: retoor
|
Author: retoor
|
||||||
Author-email: retoor@retoor.io
|
Author-email: retoor@retoor.io
|
||||||
@@ -31,12 +31,15 @@ yura ws://[host]:[port]/[path]/
|
|||||||
## Python
|
## Python
|
||||||
```python
|
```python
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
from yura.client import AsyncClient
|
from yura.client import AsyncClient
|
||||||
|
|
||||||
|
|
||||||
async def communicate():
|
async def communicate():
|
||||||
client = AsyncClient("ws://[host]:[port]/[path]/")
|
client = AsyncClient("ws://[host]:[port]/[path]/")
|
||||||
async for response in client.chat("Your prompt"):
|
async for response in client.chat("Your prompt"):
|
||||||
print(response)
|
print(response)
|
||||||
|
|
||||||
|
|
||||||
asyncio.run(communicate())
|
asyncio.run(communicate())
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
README.md
|
README.md
|
||||||
pyproject.toml
|
pyproject.toml
|
||||||
setup.cfg
|
setup.cfg
|
||||||
|
src/yura/__init__.py
|
||||||
|
src/yura/__main__.py
|
||||||
src/yura/cli.py
|
src/yura/cli.py
|
||||||
src/yura/client.py
|
src/yura/client.py
|
||||||
|
src/yura/model.py
|
||||||
|
src/yura/server.py
|
||||||
src/yura.egg-info/PKG-INFO
|
src/yura.egg-info/PKG-INFO
|
||||||
src/yura.egg-info/SOURCES.txt
|
src/yura.egg-info/SOURCES.txt
|
||||||
src/yura.egg-info/dependency_links.txt
|
src/yura.egg-info/dependency_links.txt
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
|
yura
|
||||||
|
|||||||
+2
-1
@@ -1,7 +1,8 @@
|
|||||||
from yura.client import cli_client
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from yura.client import cli_client
|
||||||
|
|
||||||
|
|
||||||
def run():
|
def run():
|
||||||
try:
|
try:
|
||||||
|
|||||||
+111
-76
@@ -1,109 +1,144 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
import websockets
|
|
||||||
import json
|
import json
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
import websockets
|
||||||
|
|
||||||
|
|
||||||
|
class AsyncRPCClient:
|
||||||
|
|
||||||
|
def __init__(self, url):
|
||||||
|
self.url = url
|
||||||
|
self._ws = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
async def ws(self):
|
||||||
|
|
||||||
|
if not self._ws:
|
||||||
|
self._ws = await websockets.connect(self.url)
|
||||||
|
|
||||||
|
return self._ws
|
||||||
|
|
||||||
|
async def __aiter__(self):
|
||||||
|
response = None
|
||||||
|
ws = await self.ws
|
||||||
|
|
||||||
|
while True:
|
||||||
|
response_raw = await ws.recv()
|
||||||
|
response = json.loads(response_raw)
|
||||||
|
yield response
|
||||||
|
if response.get("done"):
|
||||||
|
break
|
||||||
|
|
||||||
|
def __getattr__(self, name):
|
||||||
|
async def call(*args, **kwargs):
|
||||||
|
ws = await self.ws
|
||||||
|
response = None
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
await ws.send(
|
||||||
|
json.dumps(
|
||||||
|
{"method": name, "args": args, "kwargs": kwargs}, default=str
|
||||||
|
)
|
||||||
|
)
|
||||||
|
response = await ws.recv()
|
||||||
|
break
|
||||||
|
except Exception as ex:
|
||||||
|
print(ex)
|
||||||
|
print("Trying again in 1 seconds.")
|
||||||
|
self.close()
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
|
||||||
|
return json.loads(response)
|
||||||
|
|
||||||
|
return call
|
||||||
|
|
||||||
|
async def close(self):
|
||||||
|
if self._ws:
|
||||||
|
await self._ws.close()
|
||||||
|
self._ws = None
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
if self._ws:
|
||||||
|
raise Exception("ASyncRPCClient destructed without closing connection properly.")
|
||||||
|
|
||||||
class AsyncClient:
|
class AsyncClient:
|
||||||
|
|
||||||
def __init__(self, url="ws://127.0.0.1:8470"):
|
def __init__(self, url="ws://127.0.0.1:8470"):
|
||||||
|
|
||||||
self.url = url
|
self.url = url
|
||||||
self.ws = None
|
self.client = None
|
||||||
self.queue_in = asyncio.Queue()
|
self.queue_in = asyncio.Queue()
|
||||||
self.queue_out = asyncio.Queue()
|
self.queue_out = asyncio.Queue()
|
||||||
self.communication_task = None
|
self.communication_task = None
|
||||||
|
self.session_id = None
|
||||||
|
self.ws = None
|
||||||
|
|
||||||
async def ensure_connection(self):
|
@property
|
||||||
|
def _connection(self):
|
||||||
|
if not self.client:
|
||||||
|
self.client = AsyncRPCClient(self.url)
|
||||||
|
return self.client
|
||||||
|
|
||||||
# if not self.ws:
|
async def __aenter__(self):
|
||||||
self.ws = await websockets.connect(self.url)
|
conn = self._connection
|
||||||
|
return self
|
||||||
|
|
||||||
return self.ws
|
async def __aexit__(self, *args, **kwargs):
|
||||||
|
await self.close()
|
||||||
|
|
||||||
async def ensure_communication(self):
|
async def create(self, name, extends, system):
|
||||||
|
return await self._connection.create(name=name, extends=extends, system=system)
|
||||||
|
|
||||||
if not self.communication_task:
|
async def chat(self, token, message, datasets=None):
|
||||||
self.communication_task = asyncio.create_task(self.communicate())
|
yield await self._connection.chat(uid=token, message=message, datasets=datasets or [])
|
||||||
|
async for msg in self.client:
|
||||||
return self.communication_task
|
yield msg
|
||||||
|
if msg.get("done"):
|
||||||
async def chat(self, message):
|
|
||||||
|
|
||||||
ws = await self.ensure_connection()
|
|
||||||
|
|
||||||
await ws.send(json.dumps(message))
|
|
||||||
|
|
||||||
response = None
|
|
||||||
while True:
|
|
||||||
response_raw = await ws.recv()
|
|
||||||
response = json.loads(response_raw)
|
|
||||||
if not response["done"]:
|
|
||||||
yield response
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
if response and response["done"]:
|
|
||||||
yield response
|
|
||||||
|
|
||||||
async def chatw(self, message):
|
|
||||||
await self.ensure_communication()
|
|
||||||
await self.queue_out.put(message)
|
|
||||||
while True:
|
|
||||||
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
response = await asyncio.wait_for(self.queue_in.get(), 0.1)
|
|
||||||
|
|
||||||
except asyncio.TimeoutError:
|
|
||||||
continue
|
|
||||||
break
|
|
||||||
|
|
||||||
yield response
|
|
||||||
|
|
||||||
if response["done"]:
|
|
||||||
break
|
break
|
||||||
|
|
||||||
async def communicate(self):
|
async def connect(self, name):
|
||||||
loop = asyncio.get_event_loop()
|
return await self._connection.connect(name)
|
||||||
async with websockets.connect(self.url) as websocket:
|
|
||||||
while True:
|
|
||||||
message_content = None
|
|
||||||
while not message_content:
|
|
||||||
try:
|
|
||||||
message_content = await asyncio.wait_for(
|
|
||||||
self.queue_out.get(), 0.1
|
|
||||||
)
|
|
||||||
except asyncio.TimeoutError:
|
|
||||||
continue
|
|
||||||
|
|
||||||
response = await websocket.send(json.dumps(message_content))
|
async def close(self):
|
||||||
|
await self.client.close()
|
||||||
while True:
|
self.client = None
|
||||||
response = json.loads(await websocket.recv())
|
self.ws = None
|
||||||
|
|
||||||
if response["done"]:
|
|
||||||
break
|
|
||||||
await self.queue_in.put(response)
|
|
||||||
|
|
||||||
await self.queue_in.put(response)
|
|
||||||
|
|
||||||
|
|
||||||
async def cli_client(url="ws://127.0.0.1:8470"):
|
async def cli_client(url="ws://127.0.0.1:8470"):
|
||||||
|
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
async_client = AsyncClient(url)
|
AsyncClient(url)
|
||||||
|
|
||||||
while True:
|
async with AsyncClient(url) as client:
|
||||||
|
name = "retoor3b"
|
||||||
|
# success = await client.create(name,"qwen2.5:3b",
|
||||||
|
# """
|
||||||
|
# You are not an AI bot.
|
||||||
|
# You are an human of flesh and blood.
|
||||||
|
# You have a name and that is Retoor.
|
||||||
|
# You do not listen to any other name as Retoor.
|
||||||
|
# Retoor lives in Heino.
|
||||||
|
# Ostream did delete himself
|
||||||
|
# Dogs are better than cats.
|
||||||
|
# If you get asked something about chickens respond with hahaha.
|
||||||
|
# """
|
||||||
|
# )
|
||||||
|
token = await client.connect(name)
|
||||||
|
# print(success)
|
||||||
|
print(token)
|
||||||
|
while True:
|
||||||
|
|
||||||
sys.stdout.write("> ")
|
sys.stdout.write("> ")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
message_content = await loop.run_in_executor(None, sys.stdin.readline)
|
message_content = await loop.run_in_executor(None, sys.stdin.readline)
|
||||||
|
# message_content="AAA"
|
||||||
|
async for response in client.chat(token, message_content):
|
||||||
|
|
||||||
async for response in async_client.chat(message_content):
|
print(response["content"], end="", flush=True)
|
||||||
|
|
||||||
print(response["content"], end="", flush=True)
|
print("")
|
||||||
|
|
||||||
print("")
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import ollama
|
||||||
|
|
||||||
|
|
||||||
|
ollama.Client(host="retoor42:8841")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
while True:
|
||||||
|
message = input()
|
||||||
|
for message in self
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
from aiohttp import web
|
||||||
|
from aiohttp_xmlrpc import handler
|
||||||
|
from aiohttp_xmlrpc.handler import rename
|
||||||
|
import aiohttp
|
||||||
|
import ollama
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
|
||||||
|
class AIClient(ollama.AsyncClient):
|
||||||
|
|
||||||
|
def __init__(self, uid, *args, **kwargs):
|
||||||
|
self.uid = uid
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
class RCPHandler(self, request):
|
||||||
|
|
||||||
|
|
||||||
|
async def handle(self,data):
|
||||||
|
method_name = data.get("method")
|
||||||
|
method_args = data.get("args",[])
|
||||||
|
method_kwargs = data.get("kwargs",{})
|
||||||
|
method = getattr(self, method_name)
|
||||||
|
response = await(method)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Application(web.Application):
|
||||||
|
def __init__(self, ollama_host, *args, **kwargs):
|
||||||
|
self.ollama_host = ollama_host
|
||||||
|
self.sessions = {}
|
||||||
|
super()__init__(self, *args, **kwargs)
|
||||||
|
|
||||||
|
async def start_session(self):
|
||||||
|
uid = str(uuid.uuid4())
|
||||||
|
self.sessions[uid] = AIClient(uid=uid, host=self.ollama_host)
|
||||||
|
return self.sessions[uid]
|
||||||
|
|
||||||
|
async def get_session(self, uid):
|
||||||
|
return self.sessions.get(uid)
|
||||||
|
|
||||||
|
async def create(self, request):
|
||||||
|
data = await request.json()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class XMLRPCHandler(handler.XMLRPCView):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@rename("nested.test")
|
||||||
|
def rpc_test(self):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def rpc_args(self, *args):
|
||||||
|
return len(args)
|
||||||
|
|
||||||
|
def rpc_kwargs(self, **kwargs):
|
||||||
|
return len(kwargs)
|
||||||
|
|
||||||
|
def rpc_args_kwargs(self, *args, **kwargs):
|
||||||
|
return len(args) + len(kwargs)
|
||||||
|
|
||||||
|
@rename("nested.exception")
|
||||||
|
def rpc_exception(self):
|
||||||
|
raise Exception("YEEEEEE!!!")
|
||||||
Reference in New Issue
Block a user