This commit is contained in:
Vineeth Voruganti 2024-01-17 14:23:46 -08:00
parent b11d5664cf
commit d4774b7561
8 changed files with 120 additions and 108 deletions

View File

@ -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"]
#

View File

@ -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(

View File

@ -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()

View File

@ -0,0 +1,2 @@
from .client import HonchoClient
from .cache import LRUCache

View File

@ -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)

View File

@ -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()

17
sdk/poetry.lock generated
View File

@ -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"

View File

@ -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"