Skip to content

Commit

Permalink
Basic Dialectic Endpoint fixes dev-253
Browse files Browse the repository at this point in the history
  • Loading branch information
VVoruganti committed Mar 14, 2024
1 parent 8cac9b7 commit cf36895
Show file tree
Hide file tree
Showing 9 changed files with 1,075 additions and 31 deletions.
957 changes: 955 additions & 2 deletions api/poetry.lock

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion api/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ authors = ["Plastic Labs <[email protected]>"]
readme = "README.md"

[tool.poetry.dependencies]
python = "^3.8"
python = "^3.8.1"
fastapi = "^0.109.0"
uvicorn = "^0.24.0.post1"
python-dotenv = "^1.0.0"
Expand All @@ -25,6 +25,8 @@ opentelemetry-instrumentation-logging = "^0.44b0"
greenlet = "^3.0.3"
realtime = "^1.0.2"
psycopg = {extras = ["binary"], version = "^3.1.18"}
langchain = "^0.1.12"
langchain-openai = "^0.0.8"

[tool.ruff.lint]
# from https://docs.astral.sh/ruff/linter/#rule-selection example
Expand Down
70 changes: 68 additions & 2 deletions api/src/agent.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,71 @@
async def chat():
pass
import os
import uuid
from typing import Optional

from dotenv import load_dotenv
from langchain_core.prompts import (
ChatPromptTemplate,
SystemMessagePromptTemplate,
load_prompt,
)
from langchain_openai import ChatOpenAI
from sqlalchemy.ext.asyncio import AsyncSession

from . import crud, schemas

load_dotenv()

# from supabase import Client

SYSTEM_DIALECTIC = load_prompt(
os.path.join(os.path.dirname(__file__), "prompts/dialectic.yaml")
)
system_dialectic: SystemMessagePromptTemplate = SystemMessagePromptTemplate(
prompt=SYSTEM_DIALECTIC
)

llm: ChatOpenAI = ChatOpenAI(model_name="gpt-4")


async def chat(
app_id: uuid.UUID,
user_id: uuid.UUID,
session_id: uuid.UUID,
query: str,
db: AsyncSession,
):
collection = await crud.get_collection_by_name(db, app_id, user_id, "honcho")
retrieved_facts = None
if collection is None:
collection_create = schemas.CollectionCreate(name="honcho", metadata={})
collection = await crud.create_collection(
db,
collection=collection_create,
app_id=app_id,
user_id=user_id,
)
else:
retrieved_documents = await crud.query_documents(
db=db,
app_id=app_id,
user_id=user_id,
collection_id=collection.id,
query=query,
top_k=1,
)
if len(retrieved_documents) > 0:
retrieved_facts = retrieved_documents[0].content

dialectic_prompt = ChatPromptTemplate.from_messages([system_dialectic])
chain = dialectic_prompt | llm
response = await chain.ainvoke(
{
"agent_input": query,
"retrieved_facts": retrieved_facts if retrieved_facts else "None",
}
)

return schemas.AgentChat(content=response.content)


async def hydrate():
Expand Down
42 changes: 17 additions & 25 deletions api/src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
from sqlalchemy.orm import Session
from starlette.exceptions import HTTPException as StarletteHTTPException

from . import crud, schemas
from . import agent, crud, schemas
from .db import SessionLocal, engine, scaffold_db

# Otel Setup
Expand Down Expand Up @@ -1019,6 +1019,11 @@ async def create_collection(
collection: schemas.CollectionCreate,
db: AsyncSession = Depends(get_db),
):
if collection.name == "honcho":
raise HTTPException(
status_code=406,
detail="error invalid collection configuration - honcho is a reserved name",
)
try:
return await crud.create_collection(
db, collection=collection, app_id=app_id, user_id=user_id
Expand All @@ -1043,6 +1048,12 @@ async def update_collection(
raise HTTPException(
status_code=400, detail="invalid request - name cannot be None"
)
if collection.name == "honcho":
raise HTTPException(
status_code=406,
detail="error invalid collection configuration - honcho is a reserved name",
)

try:
honcho_collection = await crud.update_collection(
db,
Expand Down Expand Up @@ -1249,37 +1260,18 @@ async def delete_document(
)


@router.get("/sessions/{session_id}/chat", response_model=Sequence[schemas.Message])
@router.get("/sessions/{session_id}/chat", response_model=schemas.AgentChat)
async def get_chat(
request: Request,
app_id: uuid.UUID,
user_id: uuid.UUID,
session_id: uuid.UUID,
query: str,
db: AsyncSession = Depends(get_db),
):
pass


@router.get("/sessions/{session_id}/hydrate")
async def hydrate(
request: Request,
app_id: uuid.UUID,
user_id: uuid.UUID,
session_id: uuid.UUID,
db: AsyncSession = Depends(get_db),
):
pass


@router.get("/sessions/{session_id}/insight")
async def get_insight(
request: Request,
app_id: uuid.UUID,
user_id: uuid.UUID,
session_id: uuid.UUID,
db: AsyncSession = Depends(get_db),
):
pass
return await agent.chat(
app_id=app_id, user_id=user_id, session_id=session_id, query=query, db=db
)


app.include_router(router)
11 changes: 11 additions & 0 deletions api/src/prompts/dialectic.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

_type: prompt
input_variables:
["agent_input", "retrieved_facts"]
template: >
You are tasked with responding to the query based on the context provided.
---
query: {agent_input}
context: {retrieved_facts}
---
Provide a brief, matter-of-fact, and appropriate response to the query based on the context provided. If the context provided doesn't aid in addressing the query, return None.
4 changes: 4 additions & 0 deletions api/src/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,3 +236,7 @@ def fetch_h_metadata(cls, value, values):
class Config:
from_attributes = True
schema_extra = {"exclude": ["h_metadata"]}


class AgentChat(BaseModel):
content: str
8 changes: 8 additions & 0 deletions sdk/honcho/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -1155,6 +1155,14 @@ async def close(self):
response.raise_for_status()
self._is_active = False

async def chat(self, query) -> str:
url = f"{self.base_url}/chat"
params = {"query": query}
response = await self.user.honcho.client.get(url, params=params)
response.raise_for_status()
data = response.json()
return data["content"]


class AsyncCollection:
"""Represents a single collection for a user in an app"""
Expand Down
8 changes: 8 additions & 0 deletions sdk/honcho/sync_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -1155,6 +1155,14 @@ def close(self):
response.raise_for_status()
self._is_active = False

def chat(self, query) -> str:
url = f"{self.base_url}/chat"
params = {"query": query}
response = self.user.honcho.client.get(url, params=params)
response.raise_for_status()
data = response.json()
return data["content"]


class Collection:
"""Represents a single collection for a user in an app"""
Expand Down
2 changes: 1 addition & 1 deletion sdk/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ readme = "README.md"
packages = [{include = "honcho"}]

[tool.poetry.dependencies]
python = "^3.10"
python = "^3.8.1"
httpx = "^0.26.0"

[tool.poetry.group.test.dependencies]
Expand Down

0 comments on commit cf36895

Please sign in to comment.