Skip to content
Snippets Groups Projects
Commit bedf1992 authored by Marcus Schiesser's avatar Marcus Schiesser
Browse files

fix: throw and show error if unsupported annotation (e.g. image) is uploaded

parent c1510bd3
No related branches found
No related tags found
No related merge requests found
......@@ -123,6 +123,9 @@ class E2BCodeInterpreter:
def code_interpret(code: str) -> Dict:
"""
Execute python code in a Jupyter notebook cell and return any result, stdout, stderr, display_data, and error.
Parameters:
code (str): The python code to be executed in a single cell.
"""
api_key = os.getenv("E2B_API_KEY")
filesever_url_prefix = os.getenv("FILESERVER_URL_PREFIX")
......
......@@ -28,56 +28,58 @@ async def chat(
data: ChatData,
chat_engine: BaseChatEngine = Depends(get_chat_engine),
):
last_message_content = data.get_last_message_content()
messages = data.get_history_messages()
event_handler = EventCallbackHandler()
chat_engine.callback_manager.handlers.append(event_handler) # type: ignore
async def content_generator():
# Yield the text response
async def _chat_response_generator():
response = await chat_engine.astream_chat(last_message_content, messages)
async for token in response.async_response_gen():
yield VercelStreamResponse.convert_text(token)
# the text_generator is the leading stream, once it's finished, also finish the event stream
event_handler.is_done = True
# Yield the source nodes
yield VercelStreamResponse.convert_data(
{
"type": "sources",
"data": {
"nodes": [
SourceNodes.from_source_node(node).dict()
for node in response.source_nodes
]
},
}
)
# Yield the events from the event handler
async def _event_generator():
async for event in event_handler.async_event_gen():
event_response = event.to_response()
if event_response is not None:
yield VercelStreamResponse.convert_data(event_response)
combine = stream.merge(_chat_response_generator(), _event_generator())
is_stream_started = False
async with combine.stream() as streamer:
async for output in streamer:
if not is_stream_started:
is_stream_started = True
# Stream a blank message to start the stream
yield VercelStreamResponse.convert_text("")
yield output
if await request.is_disconnected():
break
try:
last_message_content = data.get_last_message_content()
messages = data.get_history_messages()
event_handler = EventCallbackHandler()
chat_engine.callback_manager.handlers.append(event_handler) # type: ignore
async def content_generator():
# Yield the text response
async def _chat_response_generator():
response = await chat_engine.astream_chat(
last_message_content, messages
)
async for token in response.async_response_gen():
yield VercelStreamResponse.convert_text(token)
# the text_generator is the leading stream, once it's finished, also finish the event stream
event_handler.is_done = True
# Yield the source nodes
yield VercelStreamResponse.convert_data(
{
"type": "sources",
"data": {
"nodes": [
SourceNodes.from_source_node(node).dict()
for node in response.source_nodes
]
},
}
)
# Yield the events from the event handler
async def _event_generator():
async for event in event_handler.async_event_gen():
event_response = event.to_response()
if event_response is not None:
yield VercelStreamResponse.convert_data(event_response)
combine = stream.merge(_chat_response_generator(), _event_generator())
is_stream_started = False
async with combine.stream() as streamer:
async for output in streamer:
if not is_stream_started:
is_stream_started = True
# Stream a blank message to start the stream
yield VercelStreamResponse.convert_text("")
yield output
if await request.is_disconnected():
break
return VercelStreamResponse(content=content_generator())
except Exception as e:
logger.exception("Error in chat engine", exc_info=True)
......
......@@ -39,17 +39,20 @@ class AnnotationData(BaseModel):
}
alias_generator = to_camel
def to_raw_content(self) -> str:
if self.csv_files is not None and len(self.csv_files) > 0:
return "Use data from following CSV raw contents\n" + "\n".join(
[f"```csv\n{csv_file.content}\n```" for csv_file in self.csv_files]
)
class Annotation(BaseModel):
type: str
data: AnnotationData
def to_content(self) -> str:
if self.type == "csv":
csv_files = self.data.csv_files
if csv_files is not None and len(csv_files) > 0:
return "Use data from following CSV raw contents\n" + "\n".join(
[f"```csv\n{csv_file.content}\n```" for csv_file in csv_files]
)
raise ValueError(f"Unsupported annotation type: {self.type}")
class Message(BaseModel):
role: MessageRole
......@@ -89,10 +92,9 @@ class ChatData(BaseModel):
for message in reversed(self.messages):
if message.role == MessageRole.USER and message.annotations is not None:
annotation_contents = (
annotation.data.to_raw_content()
for annotation in message.annotations
annotation.to_content() for annotation in message.annotations
)
annotation_text = "\n".join(filter(None, annotation_contents))
annotation_text = "\n".join(annotation_contents)
message_content = f"{message_content}\n{annotation_text}"
break
return message_content
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment