mirror of
https://github.com/wassname/Open-Assistant.git
synced 2026-07-13 00:50:06 +08:00
BREAKING-CHANGES: Renaming several models/database objects + API protocol
person -> user work_package -> task post -> message thread -> message_tree
This commit is contained in:
committed by
Andreas Köpf
parent
35e0c32a08
commit
8b225430a4
+8
-7
@@ -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}"
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()))
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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
@@ -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,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user