MVP SDK
This commit is contained in:
parent
b11d5664cf
commit
d4774b7561
|
|
@ -0,0 +1,37 @@
|
|||
# https://pythonspeed.com/articles/base-image-python-docker-images/
|
||||
# https://testdriven.io/blog/docker-best-practices/
|
||||
FROM python:3.10-slim-bullseye
|
||||
|
||||
RUN apt-get update && apt-get install -y build-essential
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# https://stackoverflow.com/questions/53835198/integrating-python-poetry-with-docker
|
||||
ENV PYTHONFAULTHANDLER=1 \
|
||||
PYTHONUNBUFFERED=1 \
|
||||
PYTHONHASHSEED=random \
|
||||
PIP_NO_CACHE_DIR=off \
|
||||
PIP_DISABLE_PIP_VERSION_CHECK=on \
|
||||
PIP_DEFAULT_TIMEOUT=100 \
|
||||
POETRY_VERSION=1.4.1
|
||||
|
||||
RUN pip install "poetry==$POETRY_VERSION"
|
||||
|
||||
# Copy only requirements to cache them in docker layer
|
||||
WORKDIR /app
|
||||
COPY poetry.lock pyproject.toml /app/
|
||||
|
||||
# Project initialization:
|
||||
RUN poetry config virtualenvs.create false \
|
||||
&& poetry install --no-root --no-interaction --no-ansi --without dev
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN addgroup --system app && adduser --system --group app
|
||||
USER app
|
||||
|
||||
COPY src/ src/
|
||||
|
||||
# https://stackoverflow.com/questions/29663459/python-app-does-not-print-anything-when-running-detached-in-docker
|
||||
CMD ["python", "-m", "uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]
|
||||
#
|
||||
|
|
@ -70,7 +70,7 @@ def get_session(user_id: str, session_id: int, db: Session = Depends(get_db)):
|
|||
########################################################
|
||||
|
||||
@app.post(
|
||||
"/users/{user_id}/sessions/{session_id}/messages/",
|
||||
"/users/{user_id}/sessions/{session_id}/messages",
|
||||
response_model=schemas.Message
|
||||
)
|
||||
def create_message_for_session(
|
||||
|
|
@ -85,7 +85,7 @@ def create_message_for_session(
|
|||
raise HTTPException(status_code=404, detail="Session not found")
|
||||
|
||||
@app.get(
|
||||
"/users/{user_id}/sessions/{session_id}/messages/",
|
||||
"/users/{user_id}/sessions/{session_id}/messages",
|
||||
response_model=list[schemas.Message]
|
||||
)
|
||||
def get_messages_for_session(
|
||||
|
|
|
|||
|
|
@ -1,32 +1,50 @@
|
|||
from langchain.prompts import ChatPromptTemplate
|
||||
# from langchain_community.chat_models import ChatOllama
|
||||
from langchain_community.chat_models.fake import FakeListChatModel
|
||||
from langchain.schema import HumanMessage, SystemMessage, AIMessage
|
||||
from typing import List
|
||||
|
||||
from langchain.prompts import ChatPromptTemplate
|
||||
from langchain.schema import AIMessage, HumanMessage, SystemMessage
|
||||
from langchain_community.chat_models.fake import FakeListChatModel
|
||||
|
||||
from honcho.client import HonchoClient
|
||||
# from client import HonchoClient
|
||||
|
||||
honcho = HonchoClient(base_url="http://localhost:8000")
|
||||
|
||||
# llm = ChatOllama(model="phi")
|
||||
responses = ["Fake LLM Response :)"]
|
||||
llm = FakeListChatModel(responses=responses)
|
||||
system = SystemMessage(content="You are world class technical documentation writer. Be as concise as possible")
|
||||
|
||||
memory = []
|
||||
user = "CLI-Test"
|
||||
session = honcho.create_session(user_id=user)
|
||||
session_id = session["id"]
|
||||
|
||||
def langchain_message_converter(messages: List):
|
||||
new_messages = []
|
||||
for message in messages:
|
||||
if message["is_user"]:
|
||||
new_messages.append(HumanMessage(content=message["content"]))
|
||||
else:
|
||||
new_messages.append(AIMessage(content=message["content"]))
|
||||
return new_messages
|
||||
|
||||
def chat():
|
||||
while True:
|
||||
user_input = input("User: ")
|
||||
if user_input == "exit":
|
||||
honcho.delete_session(user, session_id)
|
||||
break
|
||||
# print(user_input)
|
||||
user_mesage = HumanMessage(content=user_input)
|
||||
user_message = HumanMessage(content=user_input)
|
||||
history = honcho.get_messages_for_session(user, session_id)
|
||||
langchain_history = langchain_message_converter(history)
|
||||
prompt = ChatPromptTemplate.from_messages([
|
||||
system,
|
||||
*memory,
|
||||
user_mesage
|
||||
*langchain_history,
|
||||
user_message
|
||||
])
|
||||
chain = prompt | llm
|
||||
response = chain.invoke({})
|
||||
print(type(response))
|
||||
print(f"AI: {response.content}")
|
||||
memory.append(HumanMessage(content=user_input))
|
||||
memory.append(response)
|
||||
honcho.create_message_for_session(user, session_id, is_user=True, content=user_input)
|
||||
honcho.create_message_for_session(user, session_id, is_user=False, content=response.content)
|
||||
|
||||
chat()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
from .client import HonchoClient
|
||||
from .cache import LRUCache
|
||||
|
|
@ -1,45 +1,10 @@
|
|||
|
||||
"""
|
||||
Below is an implementation of a basic LRUcache that utilizes the built
|
||||
in OrderedDict data structure.
|
||||
"""
|
||||
from collections import OrderedDict
|
||||
import uuid
|
||||
from typing import List, Dict
|
||||
|
||||
class Session:
|
||||
"Wrapper Class for storing contexts between channels. Using an object to pass by reference avoid additional cache hits"
|
||||
def __init__(self, user_id: str, session_id: str = str(uuid.uuid4()), location_id: str = "web", metadata: Dict = {}):
|
||||
self.user_id: str = user_id
|
||||
self.session_id: str = session_id
|
||||
self.location_id: str = location_id
|
||||
self.metadata: Dict = metadata
|
||||
|
||||
def add_message(self, message_type: str, message: str,) -> None:
|
||||
self.mediator.add_message(self.session_id, self.user_id, message_type, message)
|
||||
|
||||
def messages(self, message_type: str) -> List[str]:
|
||||
return self.mediator.messages(self.session_id, self.user_id, message_type)
|
||||
|
||||
def delete(self) -> None:
|
||||
self.mediator.delete_session(self.session_id)
|
||||
|
||||
def restart(self) -> None:
|
||||
self.delete()
|
||||
representation = self.mediator.add_session(user_id=self.user_id, location_id=self.location_id)
|
||||
self.session_id: str = representation["id"]
|
||||
self.metadata = representation["metadata"]
|
||||
|
||||
# vector DB fn
|
||||
def add_texts(self, texts: List[str]) -> None:
|
||||
metadatas = [{"session_id": self.session_id, "user_id": self.user_id} for _ in range(len(texts))]
|
||||
self.mediator.vector_table.add_texts(texts, metadatas)
|
||||
|
||||
# vector DB fn
|
||||
def similarity_search(self, query: str, match_count: int = 5) :
|
||||
return self.mediator.vector_table.similarity_search(query=query, k=match_count, filter={"user_id": self.user_id})
|
||||
|
||||
class LRUCache:
|
||||
"""
|
||||
An implementation of a basic LRUcache that utilizes the built
|
||||
in OrderedDict data structure.
|
||||
"""
|
||||
def __init__(self, capacity: int):
|
||||
self.capacity = capacity
|
||||
self.cache = OrderedDict()
|
||||
|
|
@ -52,7 +17,7 @@ class LRUCache:
|
|||
self.cache.move_to_end(key)
|
||||
return self.cache[key]
|
||||
|
||||
def put(self, key: str, value: Session):
|
||||
def put(self, key: str, value):
|
||||
if key in self.cache:
|
||||
# If the key already exists, move it to the end and update the value
|
||||
self.cache.move_to_end(key)
|
||||
|
|
|
|||
|
|
@ -1,47 +1,53 @@
|
|||
from typing import Dict
|
||||
import requests
|
||||
|
||||
from dotenv import load_dotenv
|
||||
load_dotenv()
|
||||
|
||||
|
||||
class Client:
|
||||
class HonchoClient:
|
||||
def __init__(self, base_url):
|
||||
self.base_url = base_url
|
||||
|
||||
def get_sessions(self, user_id):
|
||||
url = f"{self.base_url}/"
|
||||
pass
|
||||
|
||||
def get_session(self, user_id, session_id):
|
||||
url = f"{self.base_url}/"
|
||||
pass
|
||||
|
||||
def create_session(self, user_id, location_id):
|
||||
url = f"{self.base_url}/"
|
||||
pass
|
||||
|
||||
def update_session(self, user_id, session_id):
|
||||
url = f"{self.base_url}/"
|
||||
pass
|
||||
|
||||
def delete_session(self, user_id, session_id):
|
||||
url = f"{self.base_url}/"
|
||||
pass
|
||||
|
||||
def get_messages_for_session(self, user_id, session_id):
|
||||
url = f"{self.base_url}/"
|
||||
pass
|
||||
|
||||
def create_message_for_session(self, user_id, session_id):
|
||||
url = f"{self.base_url}/"
|
||||
pass
|
||||
|
||||
def get_data(self, endpoint, params=None):
|
||||
url = f"{self.base_url}/{endpoint}"
|
||||
response = requests.get(url, params=params)
|
||||
def get_sessions(self, user_id: str):
|
||||
url = f"{self.base_url}/users/{user_id}/sessions"
|
||||
response = requests.get(url)
|
||||
return response.json()
|
||||
|
||||
def get_session(self, user_id: str, session_id: int):
|
||||
url = f"{self.base_url}/users/{user_id}/sessions/{session_id}"
|
||||
response = requests.get(url)
|
||||
return response.json()
|
||||
|
||||
def create_session(self, user_id: str, location_id: str = "default", session_data: Dict = {}):
|
||||
data = {
|
||||
"location_id": location_id,
|
||||
"session_data": session_data
|
||||
}
|
||||
url = f"{self.base_url}/users/{user_id}/sessions"
|
||||
response = requests.post(url, json=data)
|
||||
return response.json()
|
||||
|
||||
def update_session(self, user_id: str, session_id: int, session_data: Dict):
|
||||
data = {
|
||||
"session_data": session_data
|
||||
}
|
||||
url = f"{self.base_url}/users/{user_id}/sessions/{session_id}"
|
||||
response = requests.put(url, json=data)
|
||||
return response.json()
|
||||
|
||||
def delete_session(self, user_id: str, session_id: int):
|
||||
url = f"{self.base_url}/users/{user_id}/sessions/{session_id}"
|
||||
response = requests.delete(url)
|
||||
return response.json()
|
||||
|
||||
def get_messages_for_session(self, user_id: str, session_id: int):
|
||||
url = f"{self.base_url}/users/{user_id}/sessions/{session_id}/messages"
|
||||
response = requests.get(url)
|
||||
return response.json()
|
||||
|
||||
def create_message_for_session(self, user_id: str, session_id: int, is_user: bool, content: str):
|
||||
data = {
|
||||
"is_user": is_user,
|
||||
"content": content
|
||||
}
|
||||
url = f"{self.base_url}/users/{user_id}/sessions/{session_id}/messages"
|
||||
response = requests.post(url, json=data)
|
||||
return response.json()
|
||||
|
||||
|
|
|
|||
|
|
@ -124,21 +124,6 @@ files = [
|
|||
{file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "python-dotenv"
|
||||
version = "1.0.0"
|
||||
description = "Read key-value pairs from a .env file and set them as environment variables"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "python-dotenv-1.0.0.tar.gz", hash = "sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba"},
|
||||
{file = "python_dotenv-1.0.0-py3-none-any.whl", hash = "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
cli = ["click (>=5.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.31.0"
|
||||
|
|
@ -181,4 +166,4 @@ zstd = ["zstandard (>=0.18.0)"]
|
|||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.11"
|
||||
content-hash = "fddcdf1dfabb47768a391b0ef9c6a75ceed0e5cc69c7dd3c003512a7ff49275e"
|
||||
content-hash = "a5780ef8e06df616beb6eb67292099db49b8fe658fcbf22940e5e1af96a7c14e"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
[tool.poetry]
|
||||
name = "honcho-sdk"
|
||||
name = "honcho"
|
||||
version = "0.1.0"
|
||||
description = "Python Client SDK for Honcho"
|
||||
authors = ["Plastic Labs <hello@plasticlabs.ai>"]
|
||||
|
|
@ -9,7 +9,6 @@ packages = [{include = "honcho"}]
|
|||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.11"
|
||||
python-dotenv = "^1.0.0"
|
||||
requests = "^2.31.0"
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue