From 5c985c968999ca4f9545de780e5b0701d7ccbf1e Mon Sep 17 00:00:00 2001 From: dar4ds Date: Sat, 11 Nov 2023 17:48:27 -0600 Subject: [PATCH 01/13] test openai migrate command effect --- chatstream/__init__.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/chatstream/__init__.py b/chatstream/__init__.py index 90aa33c..0a5965c 100644 --- a/chatstream/__init__.py +++ b/chatstream/__init__.py @@ -44,7 +44,9 @@ if "pyodide" in sys.modules: from . import openai_pyodide as openai else: - import openai + from openai import AsyncOpenAI + + aclient = AsyncOpenAI() if sys.version_info < (3, 10): from typing_extensions import ParamSpec, TypeGuard @@ -353,14 +355,12 @@ async def perform_query(): # this Task (which would block other computation to happen, like running # reactive stuff). messages: StreamResult[ChatCompletionStreaming] = stream_to_reactive( - openai.ChatCompletion.acreate( # pyright: ignore[reportUnknownMemberType, reportGeneralTypeIssues] - model=self.model(), - api_key=self.api_key(), - messages=outgoing_messages_normalized, - stream=True, - temperature=self.temperature(), - **extra_kwargs, - ), + aclient.chat.completions.create(model=self.model(), + api_key=self.api_key(), + messages=outgoing_messages_normalized, + stream=True, + temperature=self.temperature(), + **extra_kwargs), throttle=self.throttle(), ) From ee9305a2219ca0967b0b62d086fc766cd714a02a Mon Sep 17 00:00:00 2001 From: dar4ds Date: Sat, 11 Nov 2023 18:11:10 -0600 Subject: [PATCH 02/13] issues on usage of new openai api --- chatstream/__init__.py | 5 +++-- test.py | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 test.py diff --git a/chatstream/__init__.py b/chatstream/__init__.py index 0a5965c..abb172a 100644 --- a/chatstream/__init__.py +++ b/chatstream/__init__.py @@ -46,7 +46,7 @@ else: from openai import AsyncOpenAI - aclient = AsyncOpenAI() + if sys.version_info < (3, 10): from typing_extensions import ParamSpec, TypeGuard @@ -354,9 +354,10 @@ async def perform_query(): # a separate task so that the data can come in without need to await it in # this Task (which would block other computation to happen, like running # reactive stuff). + aclient = AsyncOpenAI(api_key=self.api_key()) + messages: StreamResult[ChatCompletionStreaming] = stream_to_reactive( aclient.chat.completions.create(model=self.model(), - api_key=self.api_key(), messages=outgoing_messages_normalized, stream=True, temperature=self.temperature(), diff --git a/test.py b/test.py new file mode 100644 index 0000000..fcbccf5 --- /dev/null +++ b/test.py @@ -0,0 +1,21 @@ +import os +import subprocess + +# Define the path to your package +package_path = './chatstream' + +# Create a virtual environment +subprocess.run(['python3', '-m', 'venv', 'test_env']) + +# Activate the virtual environment +activate = '. test_env/bin/activate' + +# Install your package +subprocess.run([activate, '&&', 'pip', 'install', '-e', package_path], shell=True) + +# Run a test script +# Replace 'test_script.py' with the path to your test script +subprocess.run([activate, '&&', 'python', './examples/basic/app.py'], shell=True) + +# Deactivate the virtual environment +subprocess.run(['deactivate'], shell=True) From e81991cf759b5932330610375ed69fdab92619bf Mon Sep 17 00:00:00 2001 From: dar4ds Date: Sat, 11 Nov 2023 18:23:03 -0600 Subject: [PATCH 03/13] change chat completion subcripts for object method --- chatstream/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chatstream/__init__.py b/chatstream/__init__.py index abb172a..7210cec 100644 --- a/chatstream/__init__.py +++ b/chatstream/__init__.py @@ -257,10 +257,10 @@ async def finalize_streaming_result(): current_batch = self.streaming_chat_messages_batch() for message in current_batch: - if "content" in message["choices"][0]["delta"]: + if "content" in message.choices[0].delta: self.streaming_chat_string_pieces.set( self.streaming_chat_string_pieces() - + (message["choices"][0]["delta"]["content"],) + + (message.choices[0].delta.content,) ) finish_reason = message["choices"][0]["finish_reason"] From 45c843e9fd6325632deb3933299302f6c1af5eea Mon Sep 17 00:00:00 2001 From: dar4ds Date: Sat, 11 Nov 2023 18:30:30 -0600 Subject: [PATCH 04/13] runs but shows no output? why? --- chatstream/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/chatstream/__init__.py b/chatstream/__init__.py index 7210cec..726bed1 100644 --- a/chatstream/__init__.py +++ b/chatstream/__init__.py @@ -263,7 +263,7 @@ async def finalize_streaming_result(): + (message.choices[0].delta.content,) ) - finish_reason = message["choices"][0]["finish_reason"] + finish_reason = message.choices[0].finish_reason if finish_reason in ["stop", "length"]: # If we got here, we know that streaming_chat_string is not None. current_message_str = "".join(self.streaming_chat_string_pieces()) @@ -363,6 +363,7 @@ async def perform_query(): temperature=self.temperature(), **extra_kwargs), throttle=self.throttle(), + max_tokens=100 ) # Set this to a non-empty tuple (with a blank string), to indicate that From 0102a295e1838228f634eba862a9c46ddb154942 Mon Sep 17 00:00:00 2001 From: dar4ds Date: Sat, 11 Nov 2023 18:34:45 -0600 Subject: [PATCH 05/13] remove experimetnal notation --- chatstream/__init__.py | 3 +-- examples/controls/app.py | 6 +++--- examples/doc_query/app.py | 6 +++--- examples/dual/app.py | 12 ++++++------ examples/recipes_card/app.py | 6 +++--- 5 files changed, 16 insertions(+), 17 deletions(-) diff --git a/chatstream/__init__.py b/chatstream/__init__.py index 726bed1..d979df6 100644 --- a/chatstream/__init__.py +++ b/chatstream/__init__.py @@ -29,7 +29,6 @@ cast, ) -import shiny.experimental as x import tiktoken from htmltools import HTMLDependency from shiny import Inputs, Outputs, Session, module, reactive, render, ui @@ -420,7 +419,7 @@ def query_ui(): return ui.div() return ui.div( - x.ui.input_text_area( + ui.input_text_area( "query", None, # value="2+2", diff --git a/examples/controls/app.py b/examples/controls/app.py index 80784af..7ed0e41 100644 --- a/examples/controls/app.py +++ b/examples/controls/app.py @@ -20,10 +20,10 @@ }); """ -app_ui = x.ui.page_fillable( +app_ui = ui.page_fillable( ui.head_content(ui.tags.title("Shiny ChatGPT")), - x.ui.layout_sidebar( - x.ui.sidebar( + ui.layout_sidebar( + ui.sidebar( ui.h4("Shiny ChatGPT"), ui.hr(), ui.input_select( diff --git a/examples/doc_query/app.py b/examples/doc_query/app.py index f636e53..1fd8d4d 100644 --- a/examples/doc_query/app.py +++ b/examples/doc_query/app.py @@ -46,10 +46,10 @@ }); """ -app_ui = x.ui.page_fillable( +app_ui = ui.page_fillable( ui.head_content(ui.tags.title("Shiny Document Query")), - x.ui.layout_sidebar( - x.ui.sidebar( + ui.layout_sidebar( + ui.sidebar( ui.h4("Shiny Document Query"), ui.hr(), ui.input_file("file", "Drag to upload text or PDF files", multiple=True), diff --git a/examples/dual/app.py b/examples/dual/app.py index c2c2c4f..2ede3c4 100644 --- a/examples/dual/app.py +++ b/examples/dual/app.py @@ -15,10 +15,10 @@ }); """ -app_ui = x.ui.page_fillable( +app_ui = ui.page_fillable( ui.head_content(ui.tags.title("Shiny ChatGPT")), - x.ui.layout_sidebar( - x.ui.sidebar( + ui.layout_sidebar( + ui.sidebar( ui.h4("Shiny ChatGPT"), ui.hr(), ui.input_select( @@ -65,12 +65,12 @@ ), position="right", ), - x.ui.layout_column_wrap( + ui.layout_column_wrap( 1 / 2, - x.ui.card( + ui.card( chatstream.chat_ui("chat1"), ), - x.ui.card( + ui.card( chatstream.chat_ui("chat2"), ), ), diff --git a/examples/recipes_card/app.py b/examples/recipes_card/app.py index a10add8..555b26c 100644 --- a/examples/recipes_card/app.py +++ b/examples/recipes_card/app.py @@ -166,7 +166,7 @@ def answer_to_recipe_card(answer: str) -> ui.TagChild: def recipe_card(recipe: Recipe) -> ui.TagChild: title = None if "title" in recipe: - title = x.ui.card_header( + title = ui.card_header( {"class": "bg-dark fw-bold fs-3"}, recipe["title"], ) @@ -256,11 +256,11 @@ def recipe_card(recipe: Recipe) -> ui.TagChild: ui.a({"href": recipe["source"], "target": "_blank"}, recipe["source"]), ) - return x.ui.card( + return ui.card( title, tags, summary, - x.ui.layout_column_wrap( + ui.layout_column_wrap( None, ui.div(ingredients), ui.div(directions), From a6dd808d6489fb4efbb9c24f9cb91e8b7e6d8609 Mon Sep 17 00:00:00 2001 From: dar4ds Date: Sat, 11 Nov 2023 18:45:58 -0600 Subject: [PATCH 06/13] set max tokens and remove comma --- chatstream/__init__.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/chatstream/__init__.py b/chatstream/__init__.py index d979df6..0fe8e1b 100644 --- a/chatstream/__init__.py +++ b/chatstream/__init__.py @@ -259,7 +259,7 @@ async def finalize_streaming_result(): if "content" in message.choices[0].delta: self.streaming_chat_string_pieces.set( self.streaming_chat_string_pieces() - + (message.choices[0].delta.content,) + + (message.choices[0].delta.content) ) finish_reason = message.choices[0].finish_reason @@ -360,9 +360,9 @@ async def perform_query(): messages=outgoing_messages_normalized, stream=True, temperature=self.temperature(), - **extra_kwargs), - throttle=self.throttle(), - max_tokens=100 + **extra_kwargs, + max_tokens=100), + throttle=self.throttle() ) # Set this to a non-empty tuple (with a blank string), to indicate that @@ -378,13 +378,13 @@ def copy_messages_to_batch(): def session_messages_ui(): messages_html: list[ui.Tag] = [] for message in self.session_messages(): - if message["role"] == "system": + if message.role == "system": # Don't show system messages. continue messages_html.append( ui.div( - {"class": message["role"] + "-message"}, + {"class": message.role + "-message"}, message["content_html"], ) ) From ab8ee9bebbac42ce8a3c01944e047eb4680c4f65 Mon Sep 17 00:00:00 2001 From: dar4ds Date: Sat, 11 Nov 2023 18:46:21 -0600 Subject: [PATCH 07/13] keep al role notation --- chatstream/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chatstream/__init__.py b/chatstream/__init__.py index 0fe8e1b..0b77973 100644 --- a/chatstream/__init__.py +++ b/chatstream/__init__.py @@ -378,13 +378,13 @@ def copy_messages_to_batch(): def session_messages_ui(): messages_html: list[ui.Tag] = [] for message in self.session_messages(): - if message.role == "system": + if message["role"] == "system": # Don't show system messages. continue messages_html.append( ui.div( - {"class": message.role + "-message"}, + {"class": message["role"] + "-message"}, message["content_html"], ) ) From 35e9076ce8239b8f5b0ac5f2c468f1297a34b399 Mon Sep 17 00:00:00 2001 From: dar4ds Date: Sat, 11 Nov 2023 19:03:05 -0600 Subject: [PATCH 08/13] update if condition to check object value --- examples/basic/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/basic/app.py b/examples/basic/app.py index 97c6f56..63cef57 100644 --- a/examples/basic/app.py +++ b/examples/basic/app.py @@ -8,7 +8,7 @@ def server(input: Inputs, output: Outputs, session: Session): - chatstream.chat_server("mychat") + chatstream.chat_server("mychat", debug=True) app = App(app_ui, server) From a50f67d2ba5d77b09184cf9fa4482dd49e2ee373 Mon Sep 17 00:00:00 2001 From: dar4ds Date: Sat, 11 Nov 2023 19:13:23 -0600 Subject: [PATCH 09/13] typo keep tuple --- chatstream/__init__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/chatstream/__init__.py b/chatstream/__init__.py index 0b77973..846f663 100644 --- a/chatstream/__init__.py +++ b/chatstream/__init__.py @@ -256,16 +256,18 @@ async def finalize_streaming_result(): current_batch = self.streaming_chat_messages_batch() for message in current_batch: - if "content" in message.choices[0].delta: + if message.choices[0].delta.content is not None: self.streaming_chat_string_pieces.set( self.streaming_chat_string_pieces() + (message.choices[0].delta.content) ) finish_reason = message.choices[0].finish_reason + print(self.streaming_chat_string_pieces()) if finish_reason in ["stop", "length"]: # If we got here, we know that streaming_chat_string is not None. current_message_str = "".join(self.streaming_chat_string_pieces()) + print(current_message_str) if finish_reason == "length": current_message_str += " [Reached token limit; Type 'continue' to continue answer.]" From 0bc550eb07e31ac26a64f7a90752b14eea6d4fb7 Mon Sep 17 00:00:00 2001 From: dar4ds Date: Sat, 11 Nov 2023 19:19:21 -0600 Subject: [PATCH 10/13] remove print statemetns and keep tupples --- README.md | 3 +++ chatstream/__init__.py | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7cd3728..ba9c20f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,9 @@ chatstream for Shiny for Python =============================== +TEST: + - OBSERVE RETURNED CHAT OBJECT FROM OPEN TO REWRITE CHATSTREAM ACCCESS TO IT + The chatstream package provides a [Shiny for Python](https://shiny.rstudio.com/py/) module for building AI chat applications. Please keep in mind that this is very much a work in progress, and the API is likely to change. See [this post](https://shiny.posit.co/blog/posts/shiny-python-chatstream/) on the Shiny blog to see some examples in action! diff --git a/chatstream/__init__.py b/chatstream/__init__.py index 846f663..3e3310c 100644 --- a/chatstream/__init__.py +++ b/chatstream/__init__.py @@ -258,16 +258,16 @@ async def finalize_streaming_result(): for message in current_batch: if message.choices[0].delta.content is not None: self.streaming_chat_string_pieces.set( - self.streaming_chat_string_pieces() - + (message.choices[0].delta.content) + (self.streaming_chat_string_pieces()) + + (message.choices[0].delta.content,) # convert string to tuple thanks to comma ) finish_reason = message.choices[0].finish_reason - print(self.streaming_chat_string_pieces()) + if finish_reason in ["stop", "length"]: # If we got here, we know that streaming_chat_string is not None. current_message_str = "".join(self.streaming_chat_string_pieces()) - print(current_message_str) + if finish_reason == "length": current_message_str += " [Reached token limit; Type 'continue' to continue answer.]" From 4269ce64cb7a909162d2c3f74f68e30b6cdb45e2 Mon Sep 17 00:00:00 2001 From: dar4ds Date: Sat, 11 Nov 2023 19:20:18 -0600 Subject: [PATCH 11/13] KEEP readme as it was --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index ba9c20f..7cd3728 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,6 @@ chatstream for Shiny for Python =============================== -TEST: - - OBSERVE RETURNED CHAT OBJECT FROM OPEN TO REWRITE CHATSTREAM ACCCESS TO IT - The chatstream package provides a [Shiny for Python](https://shiny.rstudio.com/py/) module for building AI chat applications. Please keep in mind that this is very much a work in progress, and the API is likely to change. See [this post](https://shiny.posit.co/blog/posts/shiny-python-chatstream/) on the Shiny blog to see some examples in action! From 109b3177b48afb671bcd04b5a9aafa357e9d8094 Mon Sep 17 00:00:00 2001 From: dar4ds Date: Sat, 11 Nov 2023 19:24:39 -0600 Subject: [PATCH 12/13] remove test.py --- test.py | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 test.py diff --git a/test.py b/test.py deleted file mode 100644 index fcbccf5..0000000 --- a/test.py +++ /dev/null @@ -1,21 +0,0 @@ -import os -import subprocess - -# Define the path to your package -package_path = './chatstream' - -# Create a virtual environment -subprocess.run(['python3', '-m', 'venv', 'test_env']) - -# Activate the virtual environment -activate = '. test_env/bin/activate' - -# Install your package -subprocess.run([activate, '&&', 'pip', 'install', '-e', package_path], shell=True) - -# Run a test script -# Replace 'test_script.py' with the path to your test script -subprocess.run([activate, '&&', 'python', './examples/basic/app.py'], shell=True) - -# Deactivate the virtual environment -subprocess.run(['deactivate'], shell=True) From 03bbffc2599073b2294e2babdddea179a21bd300 Mon Sep 17 00:00:00 2001 From: dar4ds Date: Sat, 11 Nov 2023 22:21:59 -0600 Subject: [PATCH 13/13] update requiremetnes text --- examples/doc_query/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/doc_query/requirements.txt b/examples/doc_query/requirements.txt index 85c0d0f..6ab8e12 100644 --- a/examples/doc_query/requirements.txt +++ b/examples/doc_query/requirements.txt @@ -3,4 +3,4 @@ pypdf langchain tiktoken shiny -chatstream@git+https://github.com/wch/chatstream.git +chatstream@git+https://github.com/dar4datascience/chatstream.git