Skip to content
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

Store the image moderation and text moderation logs #3478

Open
wants to merge 27 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
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
49 changes: 37 additions & 12 deletions fastchat/conversation.py
Original file line number Diff line number Diff line change
Expand Up @@ -524,30 +524,55 @@ def to_anthropic_vision_api_messages(self):

def to_reka_api_messages(self):
from fastchat.serve.vision.image import ImageFormat
from reka import ChatMessage, TypedMediaContent, TypedText

ret = []
for i, (_, msg) in enumerate(self.messages[self.offset :]):
if i % 2 == 0:
if type(msg) == tuple:
text, images = msg
for image in images:
if image.image_format == ImageFormat.URL:
ret.append(
{"type": "human", "text": text, "media_url": image.url}
)
elif image.image_format == ImageFormat.BYTES:
if image.image_format == ImageFormat.BYTES:
ret.append(
{
"type": "human",
"text": text,
"media_url": f"data:image/{image.filetype};base64,{image.base64_str}",
}
ChatMessage(
content=[
TypedText(
type="text",
text=text,
),
TypedMediaContent(
type="image_url",
image_url=f"data:image/{image.filetype};base64,{image.base64_str}",
),
],
role="user",
)
)
else:
ret.append({"type": "human", "text": msg})
ret.append(
ChatMessage(
content=[
TypedText(
type="text",
text=msg,
)
],
role="user",
)
)
else:
if msg is not None:
ret.append({"type": "model", "text": msg})
ret.append(
ChatMessage(
content=[
TypedText(
type="text",
text=msg,
)
],
role="assistant",
)
)

return ret

Expand Down
46 changes: 22 additions & 24 deletions fastchat/serve/api_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -1076,8 +1076,13 @@ def reka_api_stream_iter(
api_key: Optional[str] = None, # default is env var CO_API_KEY
api_base: Optional[str] = None,
):
from reka.client import Reka
from reka import TypedText

api_key = api_key or os.environ["REKA_API_KEY"]

client = Reka(api_key=api_key)

use_search_engine = False
if "-online" in model_name:
model_name = model_name.replace("-online", "")
Expand All @@ -1094,34 +1099,27 @@ def reka_api_stream_iter(

# Make requests for logging
text_messages = []
for message in messages:
text_messages.append({"type": message["type"], "text": message["text"]})
for turn in messages:
for message in turn.content:
if isinstance(message, TypedText):
text_messages.append({"type": message.type, "text": message.text})
logged_request = dict(request)
logged_request["conversation_history"] = text_messages

logger.info(f"==== request ====\n{logged_request}")

response = requests.post(
api_base,
stream=True,
json=request,
headers={
"X-Api-Key": api_key,
},
response = client.chat.create_stream(
messages=messages,
max_tokens=max_new_tokens,
top_p=top_p,
model=model_name,
)

if response.status_code != 200:
error_message = response.text
logger.error(f"==== error from reka api: {error_message} ====")
yield {
"text": f"**API REQUEST ERROR** Reason: {error_message}",
"error_code": 1,
}
return

for line in response.iter_lines():
line = line.decode("utf8")
if not line.startswith("data: "):
continue
gen = json.loads(line[6:])
yield {"text": gen["text"], "error_code": 0}
for chunk in response:
try:
yield {"text": chunk.responses[0].chunk.content, "error_code": 0}
except:
yield {
"text": f"**API REQUEST ERROR** ",
"error_code": 1,
}
16 changes: 13 additions & 3 deletions fastchat/serve/gradio_block_arena_anony.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@
get_ip,
get_model_description_md,
)
from fastchat.serve.moderation.moderator import AzureAndOpenAIContentModerator
from fastchat.serve.remote_logger import get_remote_logger
from fastchat.utils import (
build_logger,
moderation_filter,
)

logger = build_logger("gradio_web_server_multi", "gradio_web_server_multi.log")
Expand Down Expand Up @@ -173,7 +173,10 @@ def share_click(state0, state1, model_selector0, model_selector1, request: gr.Re
)


SAMPLING_WEIGHTS = {}
SAMPLING_WEIGHTS = {
"gpt-4o-2024-05-13": 4,
"claude-3-5-sonnet-20240620": 4,
BabyChouSr marked this conversation as resolved.
Show resolved Hide resolved
}

# target model sampling weights will be boosted.
BATTLE_TARGETS = {}
Expand Down Expand Up @@ -201,6 +204,9 @@ def get_battle_pair(
if len(models) == 1:
return models[0], models[0]

if len(models) == 0:
raise ValueError("There are no models provided. Cannot get battle pair.")

model_weights = []
for model in models:
weight = get_sample_weight(
Expand Down Expand Up @@ -289,7 +295,11 @@ def add_text(
all_conv_text = (
all_conv_text_left[-1000:] + all_conv_text_right[-1000:] + "\nuser: " + text
)
flagged = moderation_filter(all_conv_text, model_list, do_moderation=True)

content_moderator = AzureAndOpenAIContentModerator()
flagged = content_moderator.text_moderation_filter(
all_conv_text, model_list, do_moderation=True
)
if flagged:
logger.info(f"violate moderation (anony). ip: {ip}. text: {text}")
# overwrite the original text
Expand Down
49 changes: 33 additions & 16 deletions fastchat/serve/gradio_block_arena_named.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@
get_ip,
get_model_description_md,
)
from fastchat.serve.moderation.moderator import AzureAndOpenAIContentModerator
from fastchat.serve.remote_logger import get_remote_logger
from fastchat.utils import (
build_logger,
moderation_filter,
)

logger = build_logger("gradio_web_server_multi", "gradio_web_server_multi.log")
Expand Down Expand Up @@ -174,19 +174,29 @@ def add_text(
no_change_btn,
]
* 6
+ [True]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe use a variable say show_vote_button? I see below we have a few more [True] [False]

)

model_list = [states[i].model_name for i in range(num_sides)]
all_conv_text_left = states[0].conv.get_prompt()
all_conv_text_right = states[1].conv.get_prompt()
all_conv_text = (
all_conv_text_left[-1000:] + all_conv_text_right[-1000:] + "\nuser: " + text
)
flagged = moderation_filter(all_conv_text, model_list)
if flagged:
logger.info(f"violate moderation (named). ip: {ip}. text: {text}")
# overwrite the original text
text = MODERATION_MSG
content_moderator = AzureAndOpenAIContentModerator()
text_flagged = content_moderator.text_moderation_filter(text, model_list)

if text_flagged:
logger.info(f"violate moderation. ip: {ip}. text: {text}")
content_moderator.write_to_json(get_ip(request))
BabyChouSr marked this conversation as resolved.
Show resolved Hide resolved
for i in range(num_sides):
states[i].skip_next = True
gr.Warning(MODERATION_MSG)
return (
states
+ [x.to_gradio_chatbot() for x in states]
+ [""]
+ [
no_change_btn,
]
* 6
+ [True]
)

conv = states[0].conv
if (len(conv.messages) - conv.offset) // 2 >= CONVERSATION_TURN_LIMIT:
Expand All @@ -201,6 +211,7 @@ def add_text(
no_change_btn,
]
* 6
+ [True]
)

text = text[:INPUT_CHAR_LEN_LIMIT] # Hard cut-off
Expand All @@ -217,6 +228,7 @@ def add_text(
disable_btn,
]
* 6
+ [False]
)


Expand Down Expand Up @@ -295,7 +307,11 @@ def bot_response_multi(
break


def flash_buttons():
def flash_buttons(dont_show_vote_buttons: bool = False):
if dont_show_vote_buttons:
yield [no_change_btn] * 4 + [enable_btn] * 2
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this actually ends up breaking the ui - need to keep yield + return pattern

return

btn_updates = [
[disable_btn] * 4 + [enable_btn] * 2,
[enable_btn] * 6,
Expand All @@ -321,6 +337,7 @@ def build_side_by_side_ui_named(models):
states = [gr.State() for _ in range(num_sides)]
model_selectors = [None] * num_sides
chatbots = [None] * num_sides
dont_show_vote_buttons = gr.State(False)

notice = gr.Markdown(notice_markdown, elem_id="notice_markdown")

Expand Down Expand Up @@ -476,24 +493,24 @@ def build_side_by_side_ui_named(models):
textbox.submit(
add_text,
states + model_selectors + [textbox],
states + chatbots + [textbox] + btn_list,
states + chatbots + [textbox] + btn_list + [dont_show_vote_buttons],
).then(
bot_response_multi,
states + [temperature, top_p, max_output_tokens],
states + chatbots + btn_list,
).then(
flash_buttons, [], btn_list
flash_buttons, [dont_show_vote_buttons], btn_list
)
send_btn.click(
add_text,
states + model_selectors + [textbox],
states + chatbots + [textbox] + btn_list,
states + chatbots + [textbox] + btn_list + [dont_show_vote_buttons],
).then(
bot_response_multi,
states + [temperature, top_p, max_output_tokens],
states + chatbots + btn_list,
).then(
flash_buttons, [], btn_list
flash_buttons, [dont_show_vote_buttons], btn_list
)

return states + model_selectors
Loading
Loading