alonsosilva commited on
Commit
f0f4ec9
·
1 Parent(s): 0b4deb4

Update app with extraction

Browse files
Files changed (2) hide show
  1. app.py +50 -24
  2. requirements.txt +2 -0
app.py CHANGED
@@ -5,29 +5,30 @@ import time
5
  import ipyvue
6
  import reacton
7
  from solara.alias import rv as v
 
 
 
 
 
8
 
 
9
  def use_change(el: reacton.core.Element, on_value: Callable[[Any], Any], enabled=True):
10
  """Trigger a callback when a blur events occurs or the enter key is pressed."""
11
  on_value_ref = solara.use_ref(on_value)
12
  on_value_ref.current = on_value
13
-
14
  def add_events():
15
  def on_change(widget, event, data):
16
  if enabled:
17
  on_value_ref.current(widget.v_model)
18
-
19
  widget = cast(ipyvue.VueWidget, solara.get_widget(el))
20
  if enabled:
21
  widget.on_event("blur", on_change)
22
  widget.on_event("keyup.enter", on_change)
23
-
24
  def cleanup():
25
  if enabled:
26
  widget.on_event("blur", on_change, remove=True)
27
  widget.on_event("keyup.enter", on_change, remove=True)
28
-
29
  return cleanup
30
-
31
  solara.use_effect(add_events, [enabled])
32
 
33
 
@@ -44,14 +45,11 @@ def InputTextarea(
44
  ):
45
  reactive_value = solara.use_reactive(value, on_value)
46
  del value, on_value
47
-
48
  def set_value_cast(value):
49
  reactive_value.value = str(value)
50
-
51
  def on_v_model(value):
52
  if continuous_update:
53
  set_value_cast(value)
54
-
55
  messages = []
56
  if error and isinstance(error, str):
57
  messages.append(error)
@@ -74,18 +72,21 @@ def InputTextarea(
74
  use_change(text_area, set_value_cast, enabled=not continuous_update)
75
  return text_area
76
 
 
 
 
 
 
 
 
 
 
 
77
 
78
  class MessageDict(TypedDict):
79
  role: str
80
  content: str
81
 
82
- # Streamed response emulator
83
- def response_generator():
84
- response = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
85
- for word in response.split():
86
- yield word + " "
87
- time.sleep(0.05)
88
-
89
  def add_chunk_to_ai_message(chunk: str):
90
  messages.value = [
91
  *messages.value[:-1],
@@ -95,27 +96,52 @@ def add_chunk_to_ai_message(chunk: str):
95
  },
96
  ]
97
 
98
- text_block="Alice is 18 years old, Bob is two years older and Charles is 30 years old"
 
 
 
 
 
 
 
 
99
 
100
  messages: solara.Reactive[List[MessageDict]] = solara.reactive([])
 
101
  @solara.component
102
  def Page():
 
 
103
  with solara.Column(style={"width": "70%", "padding": "50px"}):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
  user_message_count = len([m for m in messages.value if m["role"] == "user"])
105
  def send():
106
  messages.value = [*messages.value, {"role": "user", "content": "Hello"}]
107
  def response(message):
108
- messages.value = [*messages.value, {"role": "assistant", "content": ""}]
109
- for chunk in response_generator():
110
- add_chunk_to_ai_message(chunk)
 
 
 
111
  def result():
112
  if messages.value != []:
113
  response(messages.value[-1]["content"])
114
  result = solara.lab.use_task(result, dependencies=[user_message_count])
115
  InputTextarea("Enter text:", value=text_block, continuous_update=True)
116
- solara.Button(label="Extract", on_click=send)
117
- with solara.lab.ChatBox():
118
- for item in messages.value:
119
- if item["role"] != "user":
120
- solara.Markdown(item["content"])
121
  Page()
 
5
  import ipyvue
6
  import reacton
7
  from solara.alias import rv as v
8
+ import os
9
+ import openai
10
+ from openai import OpenAI
11
+ import instructor
12
+ from pydantic import BaseModel, Field
13
 
14
+ # NEEDED FOR INPUT TEXT AREA INSTEAD OF INPUT TEXT
15
  def use_change(el: reacton.core.Element, on_value: Callable[[Any], Any], enabled=True):
16
  """Trigger a callback when a blur events occurs or the enter key is pressed."""
17
  on_value_ref = solara.use_ref(on_value)
18
  on_value_ref.current = on_value
 
19
  def add_events():
20
  def on_change(widget, event, data):
21
  if enabled:
22
  on_value_ref.current(widget.v_model)
 
23
  widget = cast(ipyvue.VueWidget, solara.get_widget(el))
24
  if enabled:
25
  widget.on_event("blur", on_change)
26
  widget.on_event("keyup.enter", on_change)
 
27
  def cleanup():
28
  if enabled:
29
  widget.on_event("blur", on_change, remove=True)
30
  widget.on_event("keyup.enter", on_change, remove=True)
 
31
  return cleanup
 
32
  solara.use_effect(add_events, [enabled])
33
 
34
 
 
45
  ):
46
  reactive_value = solara.use_reactive(value, on_value)
47
  del value, on_value
 
48
  def set_value_cast(value):
49
  reactive_value.value = str(value)
 
50
  def on_v_model(value):
51
  if continuous_update:
52
  set_value_cast(value)
 
53
  messages = []
54
  if error and isinstance(error, str):
55
  messages.append(error)
 
72
  use_change(text_area, set_value_cast, enabled=not continuous_update)
73
  return text_area
74
 
75
+ # EXTRACTION
76
+ openai.api_key = os.environ['OPENAI_API_KEY']
77
+ client = instructor.from_openai(OpenAI())
78
+
79
+ class Person(BaseModel):
80
+ name: str
81
+ age: int
82
+
83
+ class People(BaseModel):
84
+ people: List[Person] = Field(..., default_factory=list)
85
 
86
  class MessageDict(TypedDict):
87
  role: str
88
  content: str
89
 
 
 
 
 
 
 
 
90
  def add_chunk_to_ai_message(chunk: str):
91
  messages.value = [
92
  *messages.value[:-1],
 
96
  },
97
  ]
98
 
99
+ text_block="Alice is 18 years old, Bob is two years older and Charles is 30 years old."
100
+
101
+ # DISPLAYED OUTPUT
102
+ @solara.component
103
+ def ChatInterface():
104
+ with solara.lab.ChatBox():
105
+ if len(messages.value)>0:
106
+ if messages.value[-1]["role"] != "user":
107
+ solara.Markdown(messages.value[-1]["content"], style={"font-size": "1.2em", "color": "blue"})
108
 
109
  messages: solara.Reactive[List[MessageDict]] = solara.reactive([])
110
+ aux = solara.reactive("")
111
  @solara.component
112
  def Page():
113
+ with solara.Head():
114
+ solara.Title("Extractor")
115
  with solara.Column(style={"width": "70%", "padding": "50px"}):
116
+ solara.Markdown("#Extractor")
117
+ solara.Markdown("Enter some text and the language model will try to extract names and ages of the people in the text. Done with :heart: by [alonsosilva](https://twitter.com/alonsosilva)")
118
+ extraction_stream = client.chat.completions.create_partial(
119
+ model="gpt-3.5-turbo",
120
+ response_model=People,
121
+ messages=[
122
+ {
123
+ "role": "user",
124
+ "content": f"Get the information about the people: {text_block}",
125
+ },
126
+ ],
127
+ stream=True,
128
+ )
129
+
130
  user_message_count = len([m for m in messages.value if m["role"] == "user"])
131
  def send():
132
  messages.value = [*messages.value, {"role": "user", "content": "Hello"}]
133
  def response(message):
134
+ for extraction in extraction_stream:
135
+ obj = extraction.model_dump()
136
+ if f"{obj}" != aux.value:
137
+ messages.value = [*messages.value, {"role": "assistant", "content": ""}]
138
+ add_chunk_to_ai_message(f"{obj}")
139
+ aux.value = f"{obj}"
140
  def result():
141
  if messages.value != []:
142
  response(messages.value[-1]["content"])
143
  result = solara.lab.use_task(result, dependencies=[user_message_count])
144
  InputTextarea("Enter text:", value=text_block, continuous_update=True)
145
+ solara.Button(label="Extract names and ages of users", on_click=send)
146
+ ChatInterface()
 
 
 
147
  Page()
requirements.txt CHANGED
@@ -1 +1,3 @@
1
  solara==1.31.0
 
 
 
1
  solara==1.31.0
2
+ openai==1.17.0
3
+ instructor==1.1.0