BREAKING-CHANGES: Renaming several models/database objects + API protocol

person -> user
work_package -> task
post -> message
thread -> message_tree
This commit is contained in:
Andreas Köpf
2022-12-30 21:31:23 +01:00
committed by Andreas Köpf
parent 35e0c32a08
commit 8b225430a4
11 changed files with 186 additions and 175 deletions
+8 -7
View File
@@ -140,20 +140,21 @@ if settings.DEBUG_USE_SEED_DATA:
),
]
for p in dummy_messages:
task = pr.fetch_task_by_message_id(p.task_message_id)
for msg in dummy_messages:
task = pr.fetch_task_by_frontend_message_id(msg.task_message_id)
if task and not task.ack:
logger.warning("Deleting unacknowledged seed data work package")
db.delete(task)
task = None
if not task:
if p.parent_message_id is None:
if msg.parent_message_id is None:
task = pr.store_task(
protocol_schema.InitialPromptTask(hint=""), message_tree_id=None, parent_message_id=None
)
else:
print("p.parent_message_id", p.parent_message_id)
parent_message = pr.fetch_message_by_frontend_message_id(p.parent_message_id, fail_if_missing=True)
parent_message = pr.fetch_message_by_frontend_message_id(
msg.parent_message_id, fail_if_missing=True
)
task = pr.store_task(
protocol_schema.AssistantReplyTask(
conversation=protocol_schema.Conversation(
@@ -163,8 +164,8 @@ if settings.DEBUG_USE_SEED_DATA:
message_tree_id=parent_message.message_tree_id,
parent_message_id=parent_message.id,
)
pr.bind_frontend_message_id(task.id, p.task_message_id)
message = pr.store_text_reply(p.text, p.task_message_id, p.user_message_id)
pr.bind_frontend_message_id(task.id, msg.task_message_id)
message = pr.store_text_reply(msg.text, msg.task_message_id, msg.user_message_id)
logger.info(
f"Inserted: message_id: {message.id}, payload: {message.payload.payload}, parent_message_id: {message.parent_id}"
+24 -18
View File
@@ -57,35 +57,39 @@ def generate_task(
case protocol_schema.TaskRequestType.user_reply:
logger.info("Generating a UserReplyTask.")
messages = pr.fetch_random_conversation("assistant")
messages = [
protocol_schema.ConversationMessage(text=m.payload.payload.text, is_assistant=(m.role == "assistant"))
for m in messages
task_messages = [
protocol_schema.ConversationMessage(
text=msg.payload.payload.text, is_assistant=(msg.role == "assistant")
)
for msg in messages
]
task = protocol_schema.UserReplyTask(conversation=protocol_schema.Conversation(messages=messages))
task = protocol_schema.UserReplyTask(conversation=protocol_schema.Conversation(messages=task_messages))
message_tree_id = messages[-1].message_tree_id
parent_message_id = messages[-1].id
case protocol_schema.TaskRequestType.assistant_reply:
logger.info("Generating a AssistantReplyTask.")
messages = pr.fetch_random_conversation("user")
messages = [
protocol_schema.ConversationMessage(text=m.payload.payload.text, is_assistant=(m.role == "assistant"))
for m in messages
task_messages = [
protocol_schema.ConversationMessage(
text=msg.payload.payload.text, is_assistant=(msg.role == "assistant")
)
for msg in messages
]
task = protocol_schema.AssistantReplyTask(conversation=protocol_schema.Conversation(messages=messages))
task = protocol_schema.AssistantReplyTask(conversation=protocol_schema.Conversation(messages=task_messages))
message_tree_id = messages[-1].message_tree_id
parent_message_id = messages[-1].id
case protocol_schema.TaskRequestType.rank_initial_prompts:
logger.info("Generating a RankInitialPromptsTask.")
messages = pr.fetch_random_initial_prompts()
task = protocol_schema.RankInitialPromptsTask(prompts=[m.payload.payload.text for m in messages])
task = protocol_schema.RankInitialPromptsTask(prompts=[msg.payload.payload.text for msg in messages])
case protocol_schema.TaskRequestType.rank_user_replies:
logger.info("Generating a RankUserRepliesTask.")
conversation, replies = pr.fetch_multiple_random_replies(message_role="assistant")
messages = [
task_messages = [
protocol_schema.ConversationMessage(
text=p.payload.payload.text,
is_assistant=(p.role == "assistant"),
@@ -95,7 +99,7 @@ def generate_task(
replies = [p.payload.payload.text for p in replies]
task = protocol_schema.RankUserRepliesTask(
conversation=protocol_schema.Conversation(
messages=messages,
messages=task_messages,
),
replies=replies,
)
@@ -104,7 +108,7 @@ def generate_task(
logger.info("Generating a RankAssistantRepliesTask.")
conversation, replies = pr.fetch_multiple_random_replies(message_role="user")
messages = [
task_messages = [
protocol_schema.ConversationMessage(
text=p.payload.payload.text,
is_assistant=(p.role == "assistant"),
@@ -113,7 +117,7 @@ def generate_task(
]
replies = [p.payload.payload.text for p in replies]
task = protocol_schema.RankAssistantRepliesTask(
conversation=protocol_schema.Conversation(messages=messages),
conversation=protocol_schema.Conversation(messages=task_messages),
replies=replies,
)
case _:
@@ -150,7 +154,7 @@ def request_task(
@router.post("/{task_id}/ack")
def acknowledge_task(
def tasks_acknowledge(
*,
db: Session = Depends(deps.get_db),
api_key: APIKey = Depends(deps.get_api_key),
@@ -168,7 +172,7 @@ def acknowledge_task(
# here we store the message id in the database for the task
logger.info(f"Frontend acknowledges task {task_id=}, {ack_request=}.")
pr.bind_frontend_message_id(task_id=task_id, message_id=ack_request.message_id)
pr.bind_frontend_message_id(task_id=task_id, frontend_message_id=ack_request.message_id)
except OasstError:
raise
@@ -179,7 +183,7 @@ def acknowledge_task(
@router.post("/{task_id}/nack")
def acknowledge_task_failure(
def tasks_acknowledge_failure(
*,
db: Session = Depends(deps.get_db),
api_key: APIKey = Depends(deps.get_api_key),
@@ -201,7 +205,7 @@ def acknowledge_task_failure(
@router.post("/interaction")
def message_interaction(
def tasks_interaction(
*,
db: Session = Depends(deps.get_db),
api_key: APIKey = Depends(deps.get_api_key),
@@ -223,7 +227,9 @@ def message_interaction(
# here we store the text reply in the database
pr.store_text_reply(
text=interaction.text, message_id=interaction.message_id, user_message_id=interaction.user_message_id
text=interaction.text,
frontend_message_id=interaction.message_id,
user_frontend_message_id=interaction.user_message_id,
)
return protocol_schema.TaskDone()
+2 -2
View File
@@ -27,8 +27,8 @@ class OasstErrorCode(IntEnum):
TASK_GENERATION_FAILED = 1005
# 2000-3000: prompt_repository
INVALID_POST_ID = 2000
POST_NOT_FOUND = 2001
INVALID_FRONTEND_MESSAGE_ID = 2000
MESSAGE_NOT_FOUND = 2001
RATING_OUT_OF_RANGE = 2002
INVALID_RANKING_VALUE = 2003
INVALID_TASK_TYPE = 2004
+1 -1
View File
@@ -3,7 +3,7 @@ import enum
from typing import Literal, Optional
from uuid import UUID
from oasst_backend.models import ApiClient, Journal, Person, Task
from oasst_backend.models import ApiClient, Journal, Task, User
from oasst_backend.models.payload_column_type import PayloadContainer, payload_type
from oasst_shared.utils import utcnow
from pydantic import BaseModel
+1 -1
View File
@@ -34,7 +34,7 @@ class Journal(SQLModel, table=True):
sa_column=sa.Column(sa.DateTime(timezone=True), nullable=False, server_default=sa.func.current_timestamp())
)
user_id: UUID = Field(nullable=True, foreign_key="user.id", index=True)
post_id: Optional[UUID] = Field(foreign_key="post.id", nullable=True)
message_id: Optional[UUID] = Field(foreign_key="message.id", nullable=True)
api_client_id: UUID = Field(foreign_key="api_client.id")
event_type: str = Field(nullable=False, max_length=200)
@@ -29,7 +29,7 @@ class Task(SQLModel, table=True):
api_client_id: UUID = Field(nullable=False, foreign_key="api_client.id")
ack: Optional[bool] = None
done: bool = Field(sa_column=sa.Column(sa.Boolean, nullable=False, server_default=false()))
frontend_ref_message_id: Optional[str] = None
frontend_message_id: Optional[str] = None
message_tree_id: Optional[UUID] = None
parent_message_id: Optional[UUID] = None
collective: bool = Field(sa_column=sa.Column(sa.Boolean, nullable=False, server_default=false()))
+80 -76
View File
@@ -7,7 +7,7 @@ import oasst_backend.models.db_payload as db_payload
from loguru import logger
from oasst_backend.exceptions import OasstError, OasstErrorCode
from oasst_backend.journal_writer import JournalWriter
from oasst_backend.models import ApiClient, User, Message, MessageReaction, TextLabels, Task
from oasst_backend.models import ApiClient, Message, MessageReaction, Task, TextLabels, User
from oasst_backend.models.payload_column_type import PayloadContainer
from oasst_shared.schemas import protocol as protocol_schema
from sqlmodel import Session, func
@@ -21,111 +21,109 @@ class PromptRepository:
self.user_id = self.user.id if self.user else None
self.journal = JournalWriter(db, api_client, self.user)
def lookup_user(self, user: protocol_schema.User) -> User:
if not user:
def lookup_user(self, client_user: protocol_schema.User) -> User:
if not client_user:
return None
user: User = (
self.db.query(User)
.filter(
User.api_client_id == self.api_client.id,
User.username == user.id,
User.auth_method == user.auth_method,
User.username == client_user.id,
User.auth_method == client_user.auth_method,
)
.first()
)
if user is None:
# user is unknown, create new record
user = User(
username=user.id,
display_name=user.display_name,
username=client_user.id,
display_name=client_user.display_name,
api_client_id=self.api_client.id,
auth_method=user.auth_method,
auth_method=client_user.auth_method,
)
self.db.add(user)
self.db.commit()
self.db.refresh(user)
elif user.display_name and user.display_name != user.display_name:
elif client_user.display_name and client_user.display_name != user.display_name:
# we found the user but the display name changed
user.display_name = user.display_name
user.display_name = client_user.display_name
self.db.add(user)
self.db.commit()
return user
def validate_message_id(self, message_id: str) -> None:
def validate_frontend_message_id(self, message_id: str) -> None:
if not isinstance(message_id, str):
raise OasstError(f"message_id must be string, not {type(message_id)}", OasstErrorCode.INVALID_POST_ID)
raise OasstError(
f"message_id must be string, not {type(message_id)}", OasstErrorCode.INVALID_FRONTEND_MESSAGE_ID
)
if not message_id:
raise OasstError("message_id must not be empty", OasstErrorCode.INVALID_POST_ID)
raise OasstError("message_id must not be empty", OasstErrorCode.INVALID_FRONTEND_MESSAGE_ID)
def bind_frontend_message_id(self, task_id: UUID, message_id: str):
self.validate_message_id(message_id)
def bind_frontend_message_id(self, task_id: UUID, frontend_message_id: str):
self.validate_frontend_message_id(frontend_message_id)
# find work package
work_pack: Task = (
self.db.query(Task)
.filter(Task.id == task_id, Task.api_client_id == self.api_client.id)
.first()
)
if work_pack is None:
raise OasstError(f"Task for task {task_id} not found", OasstErrorCode.TASK_NOT_FOUND)
if work_pack.expired:
# find task
task: Task = self.db.query(Task).filter(Task.id == task_id, Task.api_client_id == self.api_client.id).first()
if task is None:
raise OasstError(f"Task for {task_id=} not found", OasstErrorCode.TASK_NOT_FOUND)
if task.expired:
raise OasstError("Task already expired.", OasstErrorCode.TASK_EXPIRED)
if work_pack.done or work_pack.ack is not None:
if task.done or task.ack is not None:
raise OasstError("Task already updated.", OasstErrorCode.TASK_ALREADY_UPDATED)
work_pack.frontend_ref_message_id = message_id
work_pack.ack = True
task.frontend_message_id = frontend_message_id
task.ack = True
# ToDo: check race-condition, transaction
self.db.add(work_pack)
self.db.add(task)
self.db.commit()
def acknowledge_task_failure(self, task_id):
# find work package
work_pack: Task = (
self.db.query(Task)
.filter(Task.id == task_id, Task.api_client_id == self.api_client.id)
.first()
)
if work_pack is None:
raise OasstError(f"Task for task {task_id} not found", OasstErrorCode.TASK_NOT_FOUND)
if work_pack.expired:
# find task
task: Task = self.db.query(Task).filter(Task.id == task_id, Task.api_client_id == self.api_client.id).first()
if task is None:
raise OasstError(f"Task for {task_id=} not found", OasstErrorCode.TASK_NOT_FOUND)
if task.expired:
raise OasstError("Task already expired.", OasstErrorCode.TASK_EXPIRED)
if work_pack.done or work_pack.ack is not None:
if task.done or task.ack is not None:
raise OasstError("Task already updated.", OasstErrorCode.TASK_ALREADY_UPDATED)
work_pack.ack = False
task.ack = False
# ToDo: check race-condition, transaction
self.db.add(work_pack)
self.db.add(task)
self.db.commit()
def fetch_message_by_frontend_message_id(self, frontend_message_id: str, fail_if_missing: bool = True) -> Message:
self.validate_message_id(frontend_message_id)
self.validate_frontend_message_id(frontend_message_id)
message: Message = (
self.db.query(Message)
.filter(Message.api_client_id == self.api_client.id, Message.frontend_message_id == frontend_message_id)
.one_or_none()
)
if fail_if_missing and message is None:
raise OasstError(f"Message with message_id {frontend_message_id} not found.", OasstErrorCode.POST_NOT_FOUND)
raise OasstError(
f"Message with frontend_message_id {frontend_message_id} not found.", OasstErrorCode.MESSAGE_NOT_FOUND
)
return message
def fetch_task_by_message_id(self, message_id: str) -> Task:
self.validate_message_id(message_id)
def fetch_task_by_frontend_message_id(self, message_id: str) -> Task:
self.validate_frontend_message_id(message_id)
task = (
self.db.query(Task)
.filter(Task.api_client_id == self.api_client.id, Task.frontend_ref_message_id == message_id)
.filter(Task.api_client_id == self.api_client.id, Task.frontend_message_id == message_id)
.one_or_none()
)
return task
def store_text_reply(self, text: str, message_id: str, user_message_id: str, role: str = None) -> Message:
self.validate_message_id(message_id)
self.validate_message_id(user_message_id)
def store_text_reply(
self, text: str, frontend_message_id: str, user_frontend_message_id: str, role: str = None
) -> Message:
self.validate_frontend_message_id(frontend_message_id)
self.validate_frontend_message_id(user_frontend_message_id)
task = self.fetch_task_by_message_id(message_id)
task = self.fetch_task_by_frontend_message_id(frontend_message_id)
if task is None:
raise OasstError(f"Task for {message_id=} not found", OasstErrorCode.TASK_NOT_FOUND)
raise OasstError(f"Task for {frontend_message_id=} not found", OasstErrorCode.TASK_NOT_FOUND)
if task.expired:
raise OasstError("Task already expired.", OasstErrorCode.TASK_EXPIRED)
if not task.ack:
@@ -152,7 +150,7 @@ class PromptRepository:
new_message_id = uuid4()
user_message = self.insert_message(
message_id=new_message_id,
frontend_message_id=user_message_id,
frontend_message_id=user_frontend_message_id,
parent_id=task.parent_message_id,
message_tree_id=task.message_tree_id or new_message_id,
task_id=task.id,
@@ -170,17 +168,17 @@ class PromptRepository:
def store_rating(self, rating: protocol_schema.MessageRating) -> MessageReaction:
message = self.fetch_message_by_frontend_message_id(rating.message_id, fail_if_missing=True)
task = self.fetch_task_by_message_id(rating.message_id)
work_payload: db_payload.RateSummaryPayload = task.payload.payload
if type(work_payload) != db_payload.RateSummaryPayload:
task = self.fetch_task_by_frontend_message_id(rating.message_id)
task_payload: db_payload.RateSummaryPayload = task.payload.payload
if type(task_payload) != db_payload.RateSummaryPayload:
raise OasstError(
f"task payload type mismatch: {type(work_payload)=} != {db_payload.RateSummaryPayload}",
f"Task payload type mismatch: {type(task_payload)=} != {db_payload.RateSummaryPayload}",
OasstErrorCode.TASK_PAYLOAD_TYPE_MISMATCH,
)
if rating.rating < work_payload.scale.min or rating.rating > work_payload.scale.max:
if rating.rating < task_payload.scale.min or rating.rating > task_payload.scale.max:
raise OasstError(
f"Invalid rating value: {rating.rating=} not in {work_payload.scale=}",
f"Invalid rating value: {rating.rating=} not in {task_payload.scale=}",
OasstErrorCode.RATING_OUT_OF_RANGE,
)
@@ -197,20 +195,20 @@ class PromptRepository:
def store_ranking(self, ranking: protocol_schema.MessageRanking) -> MessageReaction:
# fetch task
task = self.fetch_task_by_message_id(ranking.message_id)
task = self.fetch_task_by_frontend_message_id(ranking.message_id)
if not task.collective:
task.done = True
self.db.add(task)
work_payload: db_payload.RankConversationRepliesPayload | db_payload.RankInitialPromptsPayload = (
task_payload: db_payload.RankConversationRepliesPayload | db_payload.RankInitialPromptsPayload = (
task.payload.payload
)
match type(work_payload):
match type(task_payload):
case db_payload.RankUserRepliesPayload | db_payload.RankAssistantRepliesPayload:
# validate ranking
num_replies = len(work_payload.replies)
num_replies = len(task_payload.replies)
if sorted(ranking.ranking) != list(range(num_replies)):
raise OasstError(
f"Invalid ranking submitted. Each reply index must appear exactly once ({num_replies=}).",
@@ -229,7 +227,7 @@ class PromptRepository:
case db_payload.RankInitialPromptsPayload:
# validate ranking
if sorted(ranking.ranking) != list(range(num_prompts := len(work_payload.prompts))):
if sorted(ranking.ranking) != list(range(num_prompts := len(task_payload.prompts))):
raise OasstError(
f"Invalid ranking submitted. Each reply index must appear exactly once ({num_prompts=}).",
OasstErrorCode.INVALID_RANKING_VALUE,
@@ -247,7 +245,7 @@ class PromptRepository:
case _:
raise OasstError(
f"task payload type mismatch: {type(work_payload)=} != {db_payload.RankConversationRepliesPayload}",
f"task payload type mismatch: {type(task_payload)=} != {db_payload.RankConversationRepliesPayload}",
OasstErrorCode.TASK_PAYLOAD_TYPE_MISMATCH,
)
@@ -294,7 +292,11 @@ class PromptRepository:
raise OasstError(f"Invalid task type: {type(task)=}", OasstErrorCode.INVALID_TASK_TYPE)
task = self.insert_task(
payload=payload, id=task.id, message_tree_id=message_tree_id, parent_message_id=parent_message_id, collective=collective
payload=payload,
id=task.id,
message_tree_id=message_tree_id,
parent_message_id=parent_message_id,
collective=collective,
)
assert task.id == task.id
return task
@@ -450,36 +452,38 @@ class PromptRepository:
parent = parent.filter(Message.role == message_role)
parent = parent.order_by(func.random()).limit(1)
replies = self.db.query(Message).filter(Message.parent_id.in_(parent)).order_by(func.random()).limit(max_size).all()
replies = (
self.db.query(Message).filter(Message.parent_id.in_(parent)).order_by(func.random()).limit(max_size).all()
)
if not replies:
raise OasstError("No replies found", OasstErrorCode.NO_REPLIES_FOUND)
message_tree = self.fetch_message_tree(replies[0].message_tree_id)
message_tree = {p.id: p for p in message_tree}
mt_messages = [message_tree[replies[0].parent_id]]
thread_messages = [message_tree[replies[0].parent_id]]
while True:
if not mt_messages[-1].parent_id:
if not thread_messages[-1].parent_id:
# reached start of the conversation
break
parent_message = message_tree[mt_messages[-1].parent_id]
mt_messages.append(parent_message)
parent_message = message_tree[thread_messages[-1].parent_id]
thread_messages.append(parent_message)
mt_messages = reversed(mt_messages)
thread_messages = reversed(thread_messages)
return message_tree_messages, replies
return thread_messages, replies
def fetch_message(self, message_id: UUID) -> Optional[Message]:
return self.db.query(Message).filter(Message.id == message_id).one()
def close_task(self, message_id: str, allow_personal_tasks: bool = False):
self.validate_message_id(message_id)
task = self.fetch_task_by_message_id(message_id)
def close_task(self, frontend_message_id: str, allow_personal_tasks: bool = False):
self.validate_frontend_message_id(frontend_message_id)
task = self.fetch_task_by_frontend_message_id(frontend_message_id)
if not task:
raise OasstError("Work package not found", OasstErrorCode.TASK_NOT_FOUND)
raise OasstError(f"Task for {frontend_message_id=} not found", OasstErrorCode.TASK_NOT_FOUND)
if task.expired:
raise OasstError("Work package expired", OasstErrorCode.TASK_EXPIRED)
raise OasstError("Task already expired", OasstErrorCode.TASK_EXPIRED)
if not allow_personal_tasks and not task.collective:
raise OasstError("This is not a collective task", OasstErrorCode.TASK_NOT_COLLECTIVE)
if task.done:
+1 -1
View File
@@ -67,7 +67,7 @@ class ApiClient:
return self.fetch_task(protocol_schema.TaskRequestType.random, user, collective=collective)
def ack_task(self, task_id: str, post_id: str) -> None:
req = protocol_schema.TaskAck(post_id=post_id)
req = protocol_schema.TaskAck(message_id=post_id)
return self.post(f"/api/v1/tasks/{task_id}/ack", req.dict())
def nack_task(self, task_id: str, reason: str) -> None:
+9 -9
View File
@@ -71,9 +71,9 @@ class ChannelTaskBase(AutoDestructThreadHandler):
def post_text_reply_to_post(self, user_msg: discord.Message) -> protocol_schema.Task:
return self.backend.post_interaction(
protocol_schema.TextReplyToPost(
post_id=str(self.first_message.id),
user_post_id=str(user_msg.id),
protocol_schema.TextReplyToMessage(
message_id=str(self.first_message.id),
user_message_id=str(user_msg.id),
user=self.to_api_user(user_msg.author),
text=user_msg.content,
)
@@ -92,9 +92,9 @@ class ChannelTaskBase(AutoDestructThreadHandler):
def post_ranking(self, user_msg: discord.Message, ranking: list[int]) -> protocol_schema.Task:
return self.backend.post_interaction(
protocol_schema.PostRanking(
post_id=str(self.first_message.id),
user_post_id=str(user_msg.id),
protocol_schema.MessageRanking(
message_id=str(self.first_message.id),
user_message_id=str(user_msg.id),
user=self.to_api_user(user_msg.author),
ranking=ranking,
)
@@ -236,9 +236,9 @@ class RateSummaryHandler(ChannelTaskBase):
if self.thread:
try:
self.backend.post_interaction(
protocol_schema.PostRating(
post_id=str(self.first_message.id),
user_post_id=str(interaction.id),
protocol_schema.MessageRating(
message_id=str(self.first_message.id),
user_message_id=str(interaction.id),
user=self.to_api_user(interaction.user),
rating=score,
)
+22 -22
View File
@@ -47,13 +47,13 @@ class TaskRequest(BaseModel):
class TaskAck(BaseModel):
"""The frontend acknowledges that it has received a task and created a post."""
"""The frontend acknowledges that it has received a task and created a message."""
post_id: str
message_id: str
class TaskNAck(BaseModel):
"""The frontend acknowledges that it has received a task but cannot create a post."""
"""The frontend acknowledges that it has received a task but cannot create a message."""
reason: str
@@ -61,7 +61,7 @@ class TaskNAck(BaseModel):
class TaskClose(BaseModel):
"""The frontend asks to mark task as done"""
post_id: str
message_id: str
class Task(BaseModel):
@@ -181,35 +181,35 @@ class Interaction(BaseModel):
user: User
class TextReplyToPost(Interaction):
"""A user has replied to a post with text."""
class TextReplyToMessage(Interaction):
"""A user has replied to a message with text."""
type: Literal["text_reply_to_post"] = "text_reply_to_post"
post_id: str
user_post_id: str
type: Literal["text_reply_to_message"] = "text_reply_to_message"
message_id: str
user_message_id: str
text: str
class MessageRating(Interaction):
"""A user has rated a post."""
"""A user has rated a message."""
type: Literal["post_rating"] = "message_rating"
post_id: str
type: Literal["message_rating"] = "message_rating"
message_id: str
rating: int
class MessageRanking(Interaction):
"""A user has given a ranking for a post."""
"""A user has given a ranking for a message."""
type: Literal["post_ranking"] = "message_ranking"
post_id: str
type: Literal["message_ranking"] = "message_ranking"
message_id: str
ranking: list[int]
AnyInteraction = Union[
TextReplyToPost,
PostRating,
PostRanking,
TextReplyToMessage,
MessageRating,
MessageRanking,
]
@@ -245,12 +245,12 @@ class TextLabels(BaseModel):
text: str
labels: dict[TextLabel, float]
post_id: str | None = None
message_id: str | None = None
@property
def has_post_id(self) -> bool:
"""Whether this TextLabels has a post_id."""
return bool(self.post_id)
def has_message_id(self) -> bool:
"""Whether this TextLabels has a message_id."""
return bool(self.message_id)
# check that each label value is between 0 and 1
@pydantic.validator("labels")
+37 -37
View File
@@ -13,7 +13,7 @@ app = typer.Typer()
USER = {"id": "1234", "display_name": "John Doe", "auth_method": "local"}
def _random_post_id():
def _random_message_id():
return str(random.randint(1000, 9999))
@@ -43,20 +43,20 @@ def main(backend_url: str = "http://127.0.0.1:8080", api_key: str = "DUMMY_KEY")
typer.echo(task["story"])
# acknowledge task
post_id = _random_post_id()
_post(f"/api/v1/tasks/{task['id']}/ack", {"post_id": post_id})
message_id = _random_message_id()
_post(f"/api/v1/tasks/{task['id']}/ack", {"message_id": message_id})
summary = typer.prompt("Enter your summary")
user_post_id = _random_post_id()
user_message_id = _random_message_id()
# send interaction
new_task = _post(
"/api/v1/tasks/interaction",
{
"type": "text_reply_to_post",
"post_id": post_id,
"user_post_id": user_post_id,
"type": "text_reply_to_message",
"message_id": message_id,
"user_message_id": user_message_id,
"text": summary,
"user": USER,
},
@@ -70,16 +70,16 @@ def main(backend_url: str = "http://127.0.0.1:8080", api_key: str = "DUMMY_KEY")
typer.echo(f"Rating scale: {task['scale']['min']} - {task['scale']['max']}")
# acknowledge task
post_id = _random_post_id()
_post(f"/api/v1/tasks/{task['id']}/ack", {"post_id": post_id})
message_id = _random_message_id()
_post(f"/api/v1/tasks/{task['id']}/ack", {"message_id": message_id})
rating = typer.prompt("Enter your rating", type=int)
# send interaction
new_task = _post(
"/api/v1/tasks/interaction",
{
"type": "post_rating",
"post_id": post_id,
"type": "message_rating",
"message_id": message_id,
"rating": rating,
"user": USER,
},
@@ -90,17 +90,17 @@ def main(backend_url: str = "http://127.0.0.1:8080", api_key: str = "DUMMY_KEY")
if task["hint"]:
typer.echo(f"Hint: {task['hint']}")
# acknowledge task
post_id = _random_post_id()
_post(f"/api/v1/tasks/{task['id']}/ack", {"post_id": post_id})
message_id = _random_message_id()
_post(f"/api/v1/tasks/{task['id']}/ack", {"message_id": message_id})
prompt = typer.prompt("Enter your prompt")
user_post_id = _random_post_id()
user_message_id = _random_message_id()
# send interaction
new_task = _post(
"/api/v1/tasks/interaction",
{
"type": "text_reply_to_post",
"post_id": post_id,
"user_post_id": user_post_id,
"type": "text_reply_to_message",
"message_id": message_id,
"user_message_id": user_message_id,
"text": prompt,
"user": USER,
},
@@ -115,17 +115,17 @@ def main(backend_url: str = "http://127.0.0.1:8080", api_key: str = "DUMMY_KEY")
if task["hint"]:
typer.echo(f"Hint: {task['hint']}")
# acknowledge task
post_id = _random_post_id()
_post(f"/api/v1/tasks/{task['id']}/ack", {"post_id": post_id})
message_id = _random_message_id()
_post(f"/api/v1/tasks/{task['id']}/ack", {"message_id": message_id})
reply = typer.prompt("Enter your reply")
user_post_id = _random_post_id()
user_message_id = _random_message_id()
# send interaction
new_task = _post(
"/api/v1/tasks/interaction",
{
"type": "text_reply_to_post",
"post_id": post_id,
"user_post_id": user_post_id,
"type": "text_reply_to_message",
"message_id": message_id,
"user_message_id": user_message_id,
"text": reply,
"user": USER,
},
@@ -138,17 +138,17 @@ def main(backend_url: str = "http://127.0.0.1:8080", api_key: str = "DUMMY_KEY")
for message in task["conversation"]["messages"]:
typer.echo(_render_message(message))
# acknowledge task
post_id = _random_post_id()
_post(f"/api/v1/tasks/{task['id']}/ack", {"post_id": post_id})
message_id = _random_message_id()
_post(f"/api/v1/tasks/{task['id']}/ack", {"message_id": message_id})
reply = typer.prompt("Enter your reply")
user_post_id = _random_post_id()
user_message_id = _random_message_id()
# send interaction
new_task = _post(
"/api/v1/tasks/interaction",
{
"type": "text_reply_to_post",
"post_id": post_id,
"user_post_id": user_post_id,
"type": "text_reply_to_message",
"message_id": message_id,
"user_message_id": user_message_id,
"text": reply,
"user": USER,
},
@@ -160,8 +160,8 @@ def main(backend_url: str = "http://127.0.0.1:8080", api_key: str = "DUMMY_KEY")
for idx, prompt in enumerate(task["prompts"], start=1):
typer.echo(f"{idx}: {prompt}")
# acknowledge task
post_id = _random_post_id()
_post(f"/api/v1/tasks/{task['id']}/ack", {"post_id": post_id})
message_id = _random_message_id()
_post(f"/api/v1/tasks/{task['id']}/ack", {"message_id": message_id})
ranking_str = typer.prompt("Enter the prompt numbers in order of preference, separated by commas")
ranking = [int(x) - 1 for x in ranking_str.split(",")]
@@ -170,8 +170,8 @@ def main(backend_url: str = "http://127.0.0.1:8080", api_key: str = "DUMMY_KEY")
new_task = _post(
"/api/v1/tasks/interaction",
{
"type": "post_ranking",
"post_id": post_id,
"type": "message_ranking",
"message_id": message_id,
"ranking": ranking,
"user": USER,
},
@@ -186,8 +186,8 @@ def main(backend_url: str = "http://127.0.0.1:8080", api_key: str = "DUMMY_KEY")
for idx, reply in enumerate(task["replies"], start=1):
typer.echo(f"{idx}: {reply}")
# acknowledge task
post_id = _random_post_id()
_post(f"/api/v1/tasks/{task['id']}/ack", {"post_id": post_id})
message_id = _random_message_id()
_post(f"/api/v1/tasks/{task['id']}/ack", {"message_id": message_id})
ranking_str = typer.prompt("Enter the reply numbers in order of preference, separated by commas")
ranking = [int(x) - 1 for x in ranking_str.split(",")]
@@ -196,8 +196,8 @@ def main(backend_url: str = "http://127.0.0.1:8080", api_key: str = "DUMMY_KEY")
new_task = _post(
"/api/v1/tasks/interaction",
{
"type": "post_ranking",
"post_id": post_id,
"type": "message_ranking",
"message_id": message_id,
"ranking": ranking,
"user": USER,
},