Skip to content

[LangChain] Add example programs and notebooks #85

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Oct 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
359 changes: 359 additions & 0 deletions framework/langchain/conversational_memory.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,359 @@
{
"cells": [
{
"cell_type": "markdown",
"source": [
"# CrateDB Chat Message History\n",
"\n",
"This notebook demonstrates how to use the `CrateDBChatMessageHistory`\n",
"to manage chat history in CrateDB, for supporting conversational memory."
],
"metadata": {
"collapsed": false
},
"id": "f22eab3f84cbeb37"
},
{
"cell_type": "markdown",
"source": [
"## Prerequisites\n",
"\n",
"Install required packages."
],
"metadata": {
"collapsed": false
}
},
{
"cell_type": "code",
"execution_count": 1,
"outputs": [],
"source": [
"#!pip install -r requirements.txt"
],
"metadata": {
"collapsed": false
}
},
{
"cell_type": "markdown",
"source": [
"## Configuration\n",
"\n",
"To use the storage wrapper, you will need to configure two details.\n",
"\n",
"1. Session Id - a unique identifier of the session, like user name, email, chat id etc.\n",
"2. Database connection string: An SQLAlchemy-compatible URI that specifies the database\n",
" connection. It will be passed to SQLAlchemy create_engine function."
],
"metadata": {
"collapsed": false
},
"id": "f8f2830ee9ca1e01"
},
{
"cell_type": "code",
"execution_count": 2,
"outputs": [],
"source": [
"from langchain.memory.chat_message_histories import CrateDBChatMessageHistory\n",
"\n",
"CONNECTION_STRING = \"crate://crate@localhost/?schema=notebook\"\n",
"\n",
"chat_message_history = CrateDBChatMessageHistory(\n",
"\tsession_id=\"test_session\",\n",
"\tconnection_string=CONNECTION_STRING\n",
")"
],
"metadata": {
"collapsed": false
}
},
{
"cell_type": "markdown",
"source": [
"## Basic Usage"
],
"metadata": {
"collapsed": false
}
},
{
"cell_type": "code",
"execution_count": 3,
"outputs": [],
"source": [
"chat_message_history.add_user_message(\"Hello\")\n",
"chat_message_history.add_ai_message(\"Hi\")"
],
"metadata": {
"collapsed": false,
"ExecuteTime": {
"end_time": "2023-08-28T10:04:38.077748Z",
"start_time": "2023-08-28T10:04:36.105894Z"
}
},
"id": "4576e914a866fb40"
},
{
"cell_type": "code",
"execution_count": 4,
"outputs": [
{
"data": {
"text/plain": "[HumanMessage(content='Hello', additional_kwargs={}, example=False),\n AIMessage(content='Hi', additional_kwargs={}, example=False)]"
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"chat_message_history.messages"
],
"metadata": {
"collapsed": false,
"ExecuteTime": {
"end_time": "2023-08-28T10:04:38.929396Z",
"start_time": "2023-08-28T10:04:38.915727Z"
}
},
"id": "b476688cbb32ba90"
},
{
"cell_type": "markdown",
"source": [
"## Custom Storage Model\n",
"\n",
"The default data model, which stores information about conversation messages only\n",
"has two slots for storing message details, the session id, and the message dictionary.\n",
"\n",
"If you want to store additional information, like message date, author, language etc.,\n",
"please provide an implementation for a custom message converter.\n",
"\n",
"This example demonstrates how to create a custom message converter, by implementing\n",
"the `BaseMessageConverter` interface."
],
"metadata": {
"collapsed": false
},
"id": "2e5337719d5614fd"
},
{
"cell_type": "code",
"execution_count": 5,
"outputs": [],
"source": [
"from datetime import datetime\n",
"from typing import Any\n",
"\n",
"from langchain.memory.chat_message_histories.cratedb import generate_autoincrement_identifier\n",
"from langchain.memory.chat_message_histories.sql import BaseMessageConverter\n",
"from langchain.schema import AIMessage, BaseMessage, HumanMessage, SystemMessage\n",
"\n",
"import sqlalchemy as sa\n",
"from sqlalchemy.orm import declarative_base\n",
"\n",
"\n",
"Base = declarative_base()\n",
"\n",
"\n",
"class CustomMessage(Base):\n",
"\t__tablename__ = \"custom_message_store\"\n",
"\n",
"\tid = sa.Column(sa.BigInteger, primary_key=True, default=generate_autoincrement_identifier)\n",
"\tsession_id = sa.Column(sa.Text)\n",
"\ttype = sa.Column(sa.Text)\n",
"\tcontent = sa.Column(sa.Text)\n",
"\tcreated_at = sa.Column(sa.DateTime)\n",
"\tauthor_email = sa.Column(sa.Text)\n",
"\n",
"\n",
"class CustomMessageConverter(BaseMessageConverter):\n",
"\tdef __init__(self, author_email: str):\n",
"\t\tself.author_email = author_email\n",
"\t\n",
"\tdef from_sql_model(self, sql_message: Any) -> BaseMessage:\n",
"\t\tif sql_message.type == \"human\":\n",
"\t\t\treturn HumanMessage(\n",
"\t\t\t\tcontent=sql_message.content,\n",
"\t\t\t)\n",
"\t\telif sql_message.type == \"ai\":\n",
"\t\t\treturn AIMessage(\n",
"\t\t\t\tcontent=sql_message.content,\n",
"\t\t\t)\n",
"\t\telif sql_message.type == \"system\":\n",
"\t\t\treturn SystemMessage(\n",
"\t\t\t\tcontent=sql_message.content,\n",
"\t\t\t)\n",
"\t\telse:\n",
"\t\t\traise ValueError(f\"Unknown message type: {sql_message.type}\")\n",
"\t\n",
"\tdef to_sql_model(self, message: BaseMessage, session_id: str) -> Any:\n",
"\t\tnow = datetime.now()\n",
"\t\treturn CustomMessage(\n",
"\t\t\tsession_id=session_id,\n",
"\t\t\ttype=message.type,\n",
"\t\t\tcontent=message.content,\n",
"\t\t\tcreated_at=now,\n",
"\t\t\tauthor_email=self.author_email\n",
"\t\t)\n",
"\t\n",
"\tdef get_sql_model_class(self) -> Any:\n",
"\t\treturn CustomMessage\n",
"\n",
"\n",
"if __name__ == \"__main__\":\n",
"\n",
"\tBase.metadata.drop_all(bind=sa.create_engine(CONNECTION_STRING))\n",
"\n",
"\tchat_message_history = CrateDBChatMessageHistory(\n",
"\t\tsession_id=\"test_session\",\n",
"\t\tconnection_string=CONNECTION_STRING,\n",
"\t\tcustom_message_converter=CustomMessageConverter(\n",
"\t\t\tauthor_email=\"test@example.com\"\n",
"\t\t)\n",
"\t)\n",
"\n",
"\tchat_message_history.add_user_message(\"Hello\")\n",
"\tchat_message_history.add_ai_message(\"Hi\")"
],
"metadata": {
"collapsed": false,
"ExecuteTime": {
"end_time": "2023-08-28T10:04:41.510498Z",
"start_time": "2023-08-28T10:04:41.494912Z"
}
},
"id": "fdfde84c07d071bb"
},
{
"cell_type": "code",
"execution_count": 6,
"outputs": [
{
"data": {
"text/plain": "[HumanMessage(content='Hello', additional_kwargs={}, example=False),\n AIMessage(content='Hi', additional_kwargs={}, example=False)]"
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"chat_message_history.messages"
],
"metadata": {
"collapsed": false,
"ExecuteTime": {
"end_time": "2023-08-28T10:04:43.497990Z",
"start_time": "2023-08-28T10:04:43.492517Z"
}
},
"id": "4a6a54d8a9e2856f"
},
{
"cell_type": "markdown",
"source": [
"## Custom Name for Session Column\n",
"\n",
"The session id, a unique token identifying the session, is an important property of\n",
"this subsystem. If your database table stores it in a different column, you can use\n",
"the `session_id_field_name` keyword argument to adjust the name correspondingly."
],
"metadata": {
"collapsed": false
},
"id": "622aded629a1adeb"
},
{
"cell_type": "code",
"execution_count": 8,
"outputs": [],
"source": [
"import json\n",
"import typing as t\n",
"\n",
"from langchain.memory.chat_message_histories.cratedb import generate_autoincrement_identifier, CrateDBMessageConverter\n",
"from langchain.schema import _message_to_dict\n",
"\n",
"\n",
"Base = declarative_base()\n",
"\n",
"class MessageWithDifferentSessionIdColumn(Base):\n",
"\t__tablename__ = \"message_store_different_session_id\"\n",
"\tid = sa.Column(sa.BigInteger, primary_key=True, default=generate_autoincrement_identifier)\n",
"\tcustom_session_id = sa.Column(sa.Text)\n",
"\tmessage = sa.Column(sa.Text)\n",
"\n",
"\n",
"class CustomMessageConverterWithDifferentSessionIdColumn(CrateDBMessageConverter):\n",
" def __init__(self):\n",
" self.model_class = MessageWithDifferentSessionIdColumn\n",
"\n",
" def to_sql_model(self, message: BaseMessage, custom_session_id: str) -> t.Any:\n",
" return self.model_class(\n",
" custom_session_id=custom_session_id, message=json.dumps(_message_to_dict(message))\n",
" )\n",
"\n",
"\n",
"if __name__ == \"__main__\":\n",
"\tBase.metadata.drop_all(bind=sa.create_engine(CONNECTION_STRING))\n",
"\n",
"\tchat_message_history = CrateDBChatMessageHistory(\n",
"\t\tsession_id=\"test_session\",\n",
"\t\tconnection_string=CONNECTION_STRING,\n",
"\t\tcustom_message_converter=CustomMessageConverterWithDifferentSessionIdColumn(),\n",
"\t\tsession_id_field_name=\"custom_session_id\",\n",
"\t)\n",
"\n",
"\tchat_message_history.add_user_message(\"Hello\")\n",
"\tchat_message_history.add_ai_message(\"Hi\")"
],
"metadata": {
"collapsed": false
}
},
{
"cell_type": "code",
"execution_count": 9,
"outputs": [
{
"data": {
"text/plain": "[HumanMessage(content='Hello', additional_kwargs={}, example=False),\n AIMessage(content='Hi', additional_kwargs={}, example=False)]"
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"chat_message_history.messages"
],
"metadata": {
"collapsed": false
}
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
34 changes: 34 additions & 0 deletions framework/langchain/conversational_memory.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""
Demonstrate conversational memory with CrateDB.

Synopsis::

# Install prerequisites.
pip install -r requirements.txt

# Start database.
docker run --rm -it --publish=4200:4200 crate/crate:nightly

# Run program.
export CRATEDB_CONNECTION_STRING="crate://crate@localhost/?schema=doc"
python conversational_memory.py
"""
import os
from pprint import pprint

from langchain.memory.chat_message_histories import CrateDBChatMessageHistory


def main():

chat_message_history = CrateDBChatMessageHistory(
session_id="test_session",
connection_string=os.environ.get("CRATEDB_CONNECTION_STRING")
)
chat_message_history.add_user_message("Hello")
chat_message_history.add_ai_message("Hi")
pprint(chat_message_history.messages)


if __name__ == "__main__":
main()
Loading