Compare commits

..
8 Commits
Author SHA1 Message Date
retoor 5ee4b3b720 Progress 2024-11-27 23:48:03 +01:00
retoor 89418d62b6 Progress 2024-11-27 23:46:21 +01:00
retoor 3af0443f58 Update version. 2024-11-27 21:57:31 +01:00
retoor 9a0dc06d57 Created package. 2024-11-27 21:52:59 +01:00
retoor 69a0b0ca7b Created package. 2024-11-27 21:52:35 +01:00
retoor 7e5e7dd2b4 Made package 2024-11-27 21:26:27 +01:00
retoor ad5a526124 Update readme 2024-11-24 17:11:38 +01:00
retoor 1cbf5ae4d3 Initial commit 2024-11-24 17:03:43 +01:00
41 changed files with 352 additions and 243 deletions
+1 -3
View File
@@ -1,4 +1,2 @@
.venv .venv
__pycache__ __*
.pypirc
.history
-18
View File
@@ -1,18 +0,0 @@
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
+1 -4
View File
@@ -20,15 +20,12 @@ 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())
``` ```
Binary file not shown.
BIN
View File
Binary file not shown.
+42
View File
@@ -0,0 +1,42 @@
Metadata-Version: 2.1
Name: yura
Version: 14.3.7
Summary: Yura async AI client
Author: retoor
Author-email: retoor@retoor.io
License: MIT
Requires-Python: >=3.7
Description-Content-Type: text/markdown
Requires-Dist: websockets
# Yura LLM Client for Katya server
Part of project with as target replacing the native ollama protocol. This protocol supports streaming and is usable trough https and it is possible to directly attach a web client to the backend.
## Install
```bash
pip install -e .
```
## Build
```bash
make build
```
## Command line usage
```bash
yura ws://[host]:[port]/[path]/
```
## Python
```python
import asyncio
from yura.client import AsyncClient
async def communicate():
client = AsyncClient("ws://[host]:[port]/[path]/")
async for response in client.chat("Your prompt"):
print(response)
asyncio.run(communicate())
```
+31
View File
@@ -0,0 +1,31 @@
# Yura LLM Client for Katya server
Part of project with as target replacing the native ollama protocol. This protocol supports streaming and is usable trough https and it is possible to directly attach a web client to the backend.
## Install
```bash
pip install -e .
```
## Build
```bash
make build
```
## Command line usage
```bash
yura ws://[host]:[port]/[path]/
```
## Python
```python
import asyncio
from yura.client import AsyncClient
async def communicate():
client = AsyncClient("ws://[host]:[port]/[path]/")
async for response in client.chat("Your prompt"):
print(response)
asyncio.run(communicate())
```
+3
View File
@@ -0,0 +1,3 @@
[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"
+25
View File
@@ -0,0 +1,25 @@
[metadata]
name = yura
version = 14.3.7
description = Yura async AI client
author = retoor
author_email = retoor@retoor.io
license = MIT
long_description = file: README.md
long_description_content_type = text/markdown
[options]
packages = find:
package_dir =
= src
python_requires = >=3.7
install_requires =
websockets
[options.packages.find]
where = src
[egg_info]
tag_build =
tag_date = 0
+42
View File
@@ -0,0 +1,42 @@
Metadata-Version: 2.1
Name: yura
Version: 14.3.7
Summary: Yura async AI client
Author: retoor
Author-email: retoor@retoor.io
License: MIT
Requires-Python: >=3.7
Description-Content-Type: text/markdown
Requires-Dist: websockets
# Yura LLM Client for Katya server
Part of project with as target replacing the native ollama protocol. This protocol supports streaming and is usable trough https and it is possible to directly attach a web client to the backend.
## Install
```bash
pip install -e .
```
## Build
```bash
make build
```
## Command line usage
```bash
yura ws://[host]:[port]/[path]/
```
## Python
```python
import asyncio
from yura.client import AsyncClient
async def communicate():
client = AsyncClient("ws://[host]:[port]/[path]/")
async for response in client.chat("Your prompt"):
print(response)
asyncio.run(communicate())
```
+11
View File
@@ -0,0 +1,11 @@
README.md
pyproject.toml
setup.cfg
src/yura/__init__.py
src/yura/__main__.py
src/yura/client.py
src/yura.egg-info/PKG-INFO
src/yura.egg-info/SOURCES.txt
src/yura.egg-info/dependency_links.txt
src/yura.egg-info/requires.txt
src/yura.egg-info/top_level.txt
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
websockets
+1
View File
@@ -0,0 +1 @@
yura
View File
View File
+106
View File
@@ -0,0 +1,106 @@
import asyncio
import websockets
import json
import sys
class AsyncClient:
def __init__(self, url="ws://127.0.0.1:8470"):
self.url = url
self.ws = None
self.queue_in = asyncio.Queue()
self.queue_out = asyncio.Queue()
self.communication_task = None
async def ensure_connection():
if not self.ws:
self.ws = await websockets.connect(self.url)
return self.ws
async def ensure_communication(self):
if not self.communication_task:
self.communication_task = asyncio.create_task(self.communicate())
return self.communication_task
async def chat(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
async def communicate(self):
loop = asyncio.get_event_loop()
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))
while True:
response = json.loads(await websocket.recv())
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"):
loop = asyncio.get_event_loop()
async_client = AsyncClient(url)
while True:
sys.stdout.write("> ")
sys.stdout.flush()
message_content = await loop.run_in_executor(None, sys.stdin.readline)
async for response in async_client.chat(message_content):
print(response["content"], end="", flush=True)
if response["done"]:
break
print("")
def main():
url = "ws://127.0.0.1:8470"
try:
url = sys.argv[1]
except IndexError:
pass
asyncio.run(cli_client(url))
if __name__ == "__main__":
main()
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
+6 -17
View File
@@ -1,24 +1,14 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os
import pathlib import pathlib
import os
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():
os.system("./.venv/bin/python -m pip install build")
os.system("rm -r dist")
os.system("./.venv/bin/python -m build .")
os.system("./.venv/bin/python -m pip install 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()
@@ -27,12 +17,11 @@ if "install" in args:
install() install()
if "build" in sys.argv: if "build" in sys.argv:
build() os.system("./.venv/bin/python -m pip install build")
os.system("./.venv/bin/python -m build .")
if "publish" in sys.argv: os.system("./.venv/bin/python -m pip install black")
build() os.system("./.venv/bin/python -m black .")
os.system("./.venv/bin/python -m pip install twine")
os.system("./.venv/bin/python -m twine upload --repository gitea dist/*")
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 -1
View File
@@ -1,6 +1,6 @@
[metadata] [metadata]
name = yura name = yura
version = 14.4.5 version = 14.3.7
description = Yura async AI client description = Yura async AI client
author = retoor author = retoor
author_email = retoor@retoor.io author_email = retoor@retoor.io
+2 -5
View File
@@ -1,6 +1,6 @@
Metadata-Version: 2.1 Metadata-Version: 2.1
Name: yura Name: yura
Version: 14.4.5 Version: 14.3.7
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,15 +31,12 @@ 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())
``` ```
-2
View File
@@ -5,8 +5,6 @@ src/yura/__init__.py
src/yura/__main__.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
View File
View File
+1 -2
View File
@@ -1,8 +1,7 @@
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:
+76 -111
View File
@@ -1,144 +1,109 @@
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.client = None self.ws = 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
@property async def ensure_connection(self):
def _connection(self):
if not self.client:
self.client = AsyncRPCClient(self.url)
return self.client
async def __aenter__(self): # if not self.ws:
conn = self._connection self.ws = await websockets.connect(self.url)
return self
async def __aexit__(self, *args, **kwargs): return self.ws
await self.close()
async def create(self, name, extends, system): async def ensure_communication(self):
return await self._connection.create(name=name, extends=extends, system=system)
async def chat(self, token, message, datasets=None): if not self.communication_task:
yield await self._connection.chat(uid=token, message=message, datasets=datasets or []) self.communication_task = asyncio.create_task(self.communicate())
async for msg in self.client:
yield msg return self.communication_task
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 connect(self, name): async def communicate(self):
return await self._connection.connect(name) loop = asyncio.get_event_loop()
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
async def close(self): response = await websocket.send(json.dumps(message_content))
await self.client.close()
self.client = None while True:
self.ws = None response = json.loads(await websocket.recv())
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()
AsyncClient(url) async_client = AsyncClient(url)
async with AsyncClient(url) as client: while True:
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):
print(response["content"], end="", flush=True) async for response in async_client.chat(message_content):
print("") print(response["content"], end="", flush=True)
print("")
def main(): def main():
-12
View File
@@ -1,12 +0,0 @@
import ollama
ollama.Client(host="retoor42:8841")
while True:
message = input()
for message in self
-67
View File
@@ -1,67 +0,0 @@
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!!!")