Skip to content

Commit b0fdf6f

Browse files
committed
added db
1 parent 77c3785 commit b0fdf6f

File tree

7 files changed

+150
-36
lines changed

7 files changed

+150
-36
lines changed

__init__.py

Whitespace-only changes.

langchain-remake/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.cache

langchain-remake/db.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# 1. Import necessary libraries
2+
import sqlite3 as sql
3+
import json
4+
5+
conn: sql.Connection = None
6+
# 1. Update the `create_database_and_table` function to create a "users" table
7+
def create_database_and_tables():
8+
global conn
9+
conn = sql.connect("messages.db")
10+
cur = conn.cursor()
11+
cur.execute(
12+
"""CREATE TABLE IF NOT EXISTS messages
13+
(id INTEGER PRIMARY KEY AUTOINCREMENT, user_id TEXT, sender_id TEXT, message TEXT)"""
14+
)
15+
cur.execute(
16+
"""CREATE TABLE IF NOT EXISTS users
17+
(user_id TEXT PRIMARY KEY, last_output TEXT)"""
18+
)
19+
conn.commit()
20+
return conn
21+
22+
23+
create_database_and_tables()
24+
25+
26+
# 2. Update the `save_message_to_database` function to handle separate tables for messages and users
27+
def save_message_to_database(user_id, message, sender_id):
28+
cur = conn.cursor()
29+
cur.execute(
30+
"INSERT INTO messages (user_id, sender_id, message) VALUES (?, ?, ?)",
31+
(user_id, sender_id, message),
32+
)
33+
conn.commit()
34+
35+
36+
def update_user_last_output(user_id, output):
37+
output_as_json = json.dumps(output)
38+
cur = conn.cursor()
39+
cur.execute(
40+
"INSERT OR REPLACE INTO users (user_id, last_output) VALUES (?, ?)",
41+
(user_id, output_as_json),
42+
)
43+
conn.commit()
44+
45+
def get_last_msgs(user_id, n=5):
46+
cur = conn.cursor()
47+
cur.execute(
48+
"SELECT * FROM messages WHERE user_id = ? ORDER BY id DESC LIMIT ?",
49+
(user_id, n),
50+
)
51+
msgs = cur.fetchall()
52+
return msgs
53+
54+
def get_last_context(user_id):
55+
cur = conn.cursor()
56+
cur.execute(
57+
"SELECT last_output FROM users WHERE user_id = ?",
58+
(user_id,),
59+
)
60+
context = cur.fetchone()
61+
if context:
62+
return json.loads(context[0])
63+
else:
64+
return None

langchain-remake/messages.db

40 KB
Binary file not shown.

langchain-remake/music.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@ def search(artist = None, album = None, song = None, playlist = None):
1313
query = "\n".join(query)
1414
search_type = "track" if song is not None else "playlist" if playlist is not None else "album" if album is not None else "artist"
1515
results = sp.search(q=query, type=search_type, limit=1)
16-
return results[search_type+"s"]["items"][0]
16+
return results[search_type+"s"]["items"][0], search_type
1717

langchain-remake/sherlock.py

Lines changed: 81 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,106 @@
1-
import os
2-
os.environ["LANGCHAIN_HANDLER"] = "langchain"
3-
41
from langchain.agents import Tool
52
from langchain.memory import ConversationTokenBufferMemory
63
from langchain.chat_models import ChatOpenAI
7-
from langchain.utilities import SerpAPIWrapper, BashProcess
8-
from langchain.agents import initialize_agent
4+
from langchain.utilities import GoogleSerperAPIWrapper, BashProcess
95
from langchain.agents.tools import Tool
6+
from langchain.agents import initialize_agent
7+
from langchain.schema import BaseMessage, HumanMessage, AIMessage
8+
9+
import json
1010
from tools import music_tool, HomeAssistantTool
11+
import db
1112

12-
llm=ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0.2, verbose=True)
13-
memory = ConversationTokenBufferMemory(memory_key="chat_history", return_messages=True, max_token_limit=1000, llm=llm)
13+
llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0.2, verbose=True)
14+
memory = ConversationTokenBufferMemory(
15+
memory_key="chat_history", return_messages=True, max_token_limit=1000, llm=llm
16+
)
1417

15-
search = SerpAPIWrapper()
18+
search = GoogleSerperAPIWrapper()
1619
bash = BashProcess()
1720
ha_tool = HomeAssistantTool(llm)
1821

22+
23+
def asyncify(fn):
24+
async def afn(query):
25+
return fn(query)
26+
27+
return afn
28+
29+
1930
tools = [
2031
Tool(
21-
name = "Google Search",
22-
func=search.run,
23-
description="Useful for when you need to answer questions about current events or the current state of the world. the input to this should be a single search term."
24-
),
25-
Tool(
26-
name = "Terminal",
27-
func=bash.run,
28-
description="Useful for typing bash commands for the terminal."
29-
),
30-
Tool(
31-
name = "Home Assistant Control",
32+
name="Home Assistant Control",
3233
func=ha_tool.arun,
3334
coroutine=ha_tool.arun,
34-
description="The user has a Home Assistant setup. This starts the process for changing things like lights, cameras etc. Use this tool whenever the user needs that sort of thing. Has modes and alerts. The input should be a standalone query containing all context necessary. The command should follow this format: `ENTITY(entity_keyword) Full user command with context`, example: `ENTITY(light) Turn off all lights`"
35+
description="The user has a Home Assistant setup. This starts the process for changing things like lights, cameras etc. Use this tool whenever the user needs that sort of thing. Has modes and alerts. The input should be a standalone query containing all context necessary. The command should follow this format: `ENTITY(entity_keyword) Full user command with context`, example: `ENTITY(light) Turn off all lights`",
3536
),
3637
Tool(
37-
name = "Play Music",
38+
name="Play Music",
3839
func=music_tool,
3940
coroutine=music_tool,
40-
description="Useful for playing music. The input to this command should be a string containing a JSON object with at least one of the following keys: 'artist', 'album', 'song', 'playlist'."
41+
description="Useful for playing music. The input to this command should be a string containing a JSON object with at least one of the following keys: 'artist', 'album', 'song', 'playlist'.",
42+
),
43+
Tool(
44+
name="Run a command in terminal",
45+
func=bash.run,
46+
coroutine=asyncify(bash.run),
47+
description="Run a bash command on the host computer. Might have side effects.",
48+
),
49+
Tool(
50+
name="Ask a politician and trusted news source",
51+
func=search.run,
52+
coroutine=asyncify(search.run),
53+
description="Use when you need to answer specific questions about current events or the current state of the world. The input to this should be a standalone query and search term. Don't copy the response ad-verbatim, but use it as a starting point for your own response.",
4154
),
4255
]
43-
agent_chain = initialize_agent(tools, llm, agent="chat-conversational-react-description", verbose=True, memory=memory)
56+
agent_chain = initialize_agent(
57+
tools,
58+
llm,
59+
agent="chat-conversational-react-description",
60+
verbose=True,
61+
memory=memory,
62+
)
63+
64+
65+
async def ask_sherlock(human_input: str, user_id: str) -> str:
66+
context = db.get_last_context(user_id)
67+
if context is not None:
68+
context = json.loads(context)
69+
context = [
70+
AIMessage(content=msg["m"])
71+
if msg["s"] == "AI"
72+
else HumanMessage(content=msg["m"])
73+
for msg in context
74+
]
75+
else:
76+
context = []
4477

45-
async def main():
78+
memory.chat_memory.messages = context
79+
80+
db.save_message_to_database(user_id, human_input, user_id)
81+
82+
ai_output = await agent_chain.arun(input=human_input)
83+
db.save_message_to_database(user_id, ai_output, "AI")
84+
85+
msgs: list[BaseMessage] = memory.load_memory_variables({})["chat_history"]
86+
new_context_as_str = json.dumps(
87+
[
88+
{"m": msg.content, "s": user_id if msg.type == "human" else "AI"}
89+
for msg in msgs
90+
]
91+
)
92+
db.update_user_last_output(user_id, new_context_as_str)
93+
94+
95+
async def loop():
4696
while True:
47-
res = await agent_chain.arun(input=input("sven:"))
48-
print(res)
97+
user_id = "id"
98+
human_input = input("You: ")
99+
ai_output = await ask_sherlock(human_input, user_id)
100+
print(ai_output)
101+
49102

50103
if __name__ == "__main__":
51104
import asyncio
52-
asyncio.run(main())
105+
106+
asyncio.run(loop())

langchain-remake/tools.py

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
from langchain.chat_models import ChatOpenAI
33
from langchain.schema import HumanMessage, AIMessage, SystemMessage, ChatMessage
44
from ha import ha_entities, play_music
5-
import spotipy
65
import shell
76
import music
7+
import json
88

99

1010
@tool("Play Music", return_direct=True)
@@ -16,12 +16,9 @@ def music_tool(query: str) -> str:
1616

1717
async def music_tool(query: str) -> str:
1818
"""Useful for playing music. The input to this command should be a string containing a JSON object with at least one of the following keys: 'artist', 'album', 'song', 'playlist'."""
19-
print(query)
20-
2119
artist, album, song, playlist = None, None, None, None
2220
# parse query as json object
2321
try:
24-
import json
2522
query = json.loads(query)
2623
artist = query.get("artist")
2724
album = query.get("album")
@@ -30,16 +27,14 @@ async def music_tool(query: str) -> str:
3027
except:
3128
pass
3229

33-
result = music.search(artist=artist, album=album, song=song, playlist=playlist)
30+
result, music_type = music.search(artist=artist, album=album, song=song, playlist=playlist)
3431

35-
print(artist, album, song, playlist)
36-
print(result["uri"], result["name"])
3732
res = play_music(result["uri"])
3833
if res != 200:
3934
print(res)
4035
return "Failed"
4136

42-
return "Success!"
37+
return f"Now playing {music_type} {result['name']}"
4338

4439
def parse_code(code: str) -> str:
4540
if "```python" in code:

0 commit comments

Comments
 (0)