-
Notifications
You must be signed in to change notification settings - Fork 343
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
Feat/continue generate #361
Changes from 3 commits
2064e55
a29ea9d
ced399b
4101c20
4221761
4ff11ef
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -181,7 +181,18 @@ def process_chat_input( | |
node_id=chat_input.message.parent_message_id, | ||
message_map=message_map, | ||
) | ||
messages.append(chat_input.message) # type: ignore | ||
|
||
continueGenerate = False | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 仮にddbに永続化されたものだけで判定が不可能である場合、この変数(continueGenerate)はprepare_conversationで返したほうが良いかと思いました(タプルに追加する)。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
これは↑の改修とすこし絡みそうなので相談させてください
単に修正漏れです。こちらの変数を There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 上記のコメント(continue_generateをinputに追加・保存前にtrim)を反映した場合、下記のようにシンプルになるかと思いましたが、いかがでしょうか? if not chat_input.continue_generate:
messages.append(chat_input.message)
args = compose_args(
...略...
def on_stop(arg: OnStopInput, **kwargs) -> None:
if chat_input.continue_generate:
# For continue generate
conversation.message_map[conversation.last_message_id].content[
0
].body += arg.full_token
else:
...略... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. こちら、 |
||
|
||
# TODO: 空メッセージだと続けて生成するとしているが、見直しが必要 | ||
if chat_input.message.content[0].body != "": | ||
messages.append(chat_input.message) # type: ignore | ||
else: | ||
if messages[-1].role == "assistant": | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
ここでtrim処理をしなければならないメッセージは必ず
となると、前段で行なっている There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
すみません、確かにtrace_to_root後に適用する必要がありますね。ご指摘ありがとうございます! AnthropicStreamHandlerの場合: class AnthropicStreamHandler(BaseStreamHandler):
"""Stream handler for Anthropic models."""
def run(self, args: dict):
...
if isinstance(event, ContentBlockDeltaEvent):
...
elif isinstance(event, MessageDeltaEvent):
...
elif isinstance(event, MessageStopEvent):
concatenated = "".join(completions)
metrics = event.model_dump()["amazon-bedrock-invocationMetrics"]
input_token_count = metrics.get("inputTokenCount")
output_token_count = metrics.get("outputTokenCount")
price = calculate_price(
self.model, input_token_count, output_token_count
)
response = self.on_stop(
OnStopInput(
+ full_token=concatenated.strip(),
stop_reason=stop_reason,
input_token_count=input_token_count,
output_token_count=output_token_count,
price=price,
)
)
yield response
else:
continue 非ストリーム処理で利用される |
||
messages[-1].content[0].body = ( | ||
messages[-1].content[0].body.strip() | ||
) # TODO: ここでstripをすることで、最終的なメッセージに影響が出ないか確認 | ||
continueGenerate = True | ||
|
||
args = compose_args( | ||
messages, | ||
|
@@ -203,43 +214,58 @@ def on_stream(token: str, **kwargs) -> None: | |
gatewayapi.post_to_connection(ConnectionId=connection_id, Data=data_to_send) | ||
|
||
def on_stop(arg: OnStopInput, **kwargs) -> None: | ||
used_chunks = None | ||
if bot and bot.display_retrieved_chunks: | ||
if len(search_results) > 0: | ||
used_chunks = [] | ||
for r in filter_used_results(arg.full_token, search_results): | ||
content_type, source_link = get_source_link(r.source) | ||
used_chunks.append( | ||
ChunkModel( | ||
content=r.content, | ||
content_type=content_type, | ||
source=source_link, | ||
rank=r.rank, | ||
if not continueGenerate: | ||
statefb marked this conversation as resolved.
Show resolved
Hide resolved
|
||
used_chunks = None | ||
if bot and bot.display_retrieved_chunks: | ||
if len(search_results) > 0: | ||
used_chunks = [] | ||
for r in filter_used_results(arg.full_token, search_results): | ||
content_type, source_link = get_source_link(r.source) | ||
used_chunks.append( | ||
ChunkModel( | ||
content=r.content, | ||
content_type=content_type, | ||
source=source_link, | ||
rank=r.rank, | ||
) | ||
) | ||
|
||
# Append entire completion as the last message | ||
assistant_msg_id = str(ULID()) | ||
message = MessageModel( | ||
role="assistant", | ||
content=[ | ||
ContentModel( | ||
content_type="text", body=arg.full_token, media_type=None | ||
) | ||
], | ||
model=chat_input.message.model, | ||
children=[], | ||
parent=user_msg_id, | ||
create_time=get_current_time(), | ||
feedback=None, | ||
used_chunks=used_chunks, | ||
thinking_log=None, | ||
) | ||
conversation.message_map[assistant_msg_id] = message | ||
# Append children to parent | ||
conversation.message_map[user_msg_id].children.append(assistant_msg_id) | ||
conversation.last_message_id = assistant_msg_id | ||
|
||
# Append entire completion as the last message | ||
assistant_msg_id = str(ULID()) | ||
message = MessageModel( | ||
role="assistant", | ||
content=[ | ||
ContentModel(content_type="text", body=arg.full_token, media_type=None) | ||
], | ||
model=chat_input.message.model, | ||
children=[], | ||
parent=user_msg_id, | ||
create_time=get_current_time(), | ||
feedback=None, | ||
used_chunks=used_chunks, | ||
thinking_log=None, | ||
) | ||
conversation.message_map[assistant_msg_id] = message | ||
# Append children to parent | ||
conversation.message_map[user_msg_id].children.append(assistant_msg_id) | ||
conversation.last_message_id = assistant_msg_id | ||
else: | ||
# For continue generate | ||
conversation.message_map[conversation.last_message_id].content[ | ||
0 | ||
].body += arg.full_token | ||
|
||
conversation.total_price += arg.price | ||
|
||
# If continued, save the state | ||
if arg.stop_reason == "max_tokens": | ||
statefb marked this conversation as resolved.
Show resolved
Hide resolved
|
||
conversation.should_continue = True | ||
else: | ||
conversation.should_continue = False | ||
|
||
# Store conversation before finish streaming so that front-end can avoid 404 issue | ||
store_conversation(user_id, conversation) | ||
last_data_to_send = json.dumps( | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -157,12 +157,13 @@ const ChatMessage: React.FC<Props> = (props) => { | |
); | ||
} else { | ||
return ( | ||
<React.Fragment key={idx}> | ||
{content.body.split('\n').map((c, idxBody) => ( | ||
<div key={idxBody}>{c}</div> | ||
))} | ||
</React.Fragment> | ||
); | ||
// [Customize]インプットメッセージもMarkdown書式で整形表示できるよう修正 | ||
<ChatMessageMarkdown | ||
key={idx} | ||
messageId={String(idx)}> | ||
{content.body} | ||
</ChatMessageMarkdown> | ||
); | ||
Comment on lines
+160
to
+166
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 自身の入力データはRawな状態で表示しておきたいです。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ファイルアップロード時に表示する関係でマークダウンにしたと思うんですが、ファイルの中身は基本的に非表示として、クリックしたら中身が見れるようなUXにしたいです(コードを読み進めて気づきました) |
||
} | ||
})} | ||
<ModalDialog | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
仮に必要な場合は、bedrock claude chatは空メッセージをフロントから受け付けない仕様なので、空の判定で良いと思います!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
仮に
max_tokens
となって続きがあったとしても、それを無視して別のリクエストを送るケースもあるかもという想定からです。should_continue
に頼ってしまうとユーザの意図した動作とならない可能性があります。了解です。
単に
text
でない場合の仕様をしっかり読み解けておらず、image
の場合にbody
が空の場合があるのかな?という想定からです。content_tyepが"image"の場合もbody
が空という状況はない感じでしょうか?分岐の直前にコメントで入れておきます。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ありがとうございます、理解しました!
別途slackでの議論の通りなのですが、空文字に意味を持たせたくないので、項目追加でお願いします!下記のようにChatInput (BE)と、PostMessageRequest (FE) に追加すればOKだと思います!