feat: [api] Various changes to get the adventure possible choice feature working
This commit is contained in:
parent
e40574ae9d
commit
461473d379
4 changed files with 32 additions and 6 deletions
|
|
@ -144,6 +144,7 @@ class AdventureService:
|
||||||
self,
|
self,
|
||||||
adventure_id: uuid.UUID,
|
adventure_id: uuid.UUID,
|
||||||
entry_id: uuid.UUID,
|
entry_id: uuid.UUID,
|
||||||
|
user_id: uuid.UUID,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Full entry generation pipeline. Called from the worker queue.
|
"""Full entry generation pipeline. Called from the worker queue.
|
||||||
|
|
||||||
|
|
@ -157,6 +158,7 @@ class AdventureService:
|
||||||
assert adventure is not None, f"Adventure {adventure_id} not found"
|
assert adventure is not None, f"Adventure {adventure_id} not found"
|
||||||
|
|
||||||
all_entries = await self.entry_repo.list_for_adventure(adventure_id)
|
all_entries = await self.entry_repo.list_for_adventure(adventure_id)
|
||||||
|
all_decisions = [await self.decision_repo.get_for_entry_and_user(entry_id=uuid.UUID(e.id), user_id=user_id) for e in all_entries]
|
||||||
current_entry = next(e for e in all_entries if e.id == str(entry_id))
|
current_entry = next(e for e in all_entries if e.id == str(entry_id))
|
||||||
is_first_entry = current_entry.entry_index == 0
|
is_first_entry = current_entry.entry_index == 0
|
||||||
is_final_entry = current_entry.entry_index + 1 == adventure.max_entry_count
|
is_final_entry = current_entry.entry_index + 1 == adventure.max_entry_count
|
||||||
|
|
@ -184,6 +186,7 @@ class AdventureService:
|
||||||
vibes=adventure.vibes,
|
vibes=adventure.vibes,
|
||||||
protagonist=adventure.protagonist,
|
protagonist=adventure.protagonist,
|
||||||
prior_entries=prior_entries,
|
prior_entries=prior_entries,
|
||||||
|
prior_decisions=all_decisions,
|
||||||
)
|
)
|
||||||
|
|
||||||
raw_text, usage_dict = await self.anthropic_client.complete(
|
raw_text, usage_dict = await self.anthropic_client.complete(
|
||||||
|
|
@ -192,7 +195,7 @@ class AdventureService:
|
||||||
max_tokens=2048,
|
max_tokens=2048,
|
||||||
)
|
)
|
||||||
|
|
||||||
story_text, choices_parsed, gm_notes, story_so_far = parse_entry_response(raw_text)
|
story_text, choices_parsed, gm_notes = parse_entry_response(raw_text)
|
||||||
|
|
||||||
await self.entry_repo.update_content(
|
await self.entry_repo.update_content(
|
||||||
entry_id=entry_id,
|
entry_id=entry_id,
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,7 @@ def build_conversation_messages(
|
||||||
vibes: list[str],
|
vibes: list[str],
|
||||||
protagonist: list[str],
|
protagonist: list[str],
|
||||||
prior_entries: list[tuple[AdventureEntry, list[AdventureEntryPossibleChoice], str | None]],
|
prior_entries: list[tuple[AdventureEntry, list[AdventureEntryPossibleChoice], str | None]],
|
||||||
|
prior_decisions: list[AdventureEntryPossibleChoice | None],
|
||||||
) -> list[dict]:
|
) -> list[dict]:
|
||||||
"""Build the full messages array for an Anthropic API call.
|
"""Build the full messages array for an Anthropic API call.
|
||||||
|
|
||||||
|
|
@ -110,8 +111,22 @@ def build_conversation_messages(
|
||||||
messages.append(
|
messages.append(
|
||||||
{"role": "assistant", "content": reconstruct_assistant_message(entry, choices)}
|
{"role": "assistant", "content": reconstruct_assistant_message(entry, choices)}
|
||||||
)
|
)
|
||||||
if chosen_label is not None:
|
|
||||||
messages.append({"role": "user", "content": chosen_label})
|
# Find the player's decision for this entry
|
||||||
|
choice_ids = [c.id for c in choices]
|
||||||
|
decision_for_entry = next(
|
||||||
|
(d for d in prior_decisions if d and d.choice_id in choice_ids),
|
||||||
|
None
|
||||||
|
)
|
||||||
|
|
||||||
|
# If a decision exists, append the player's chosen option
|
||||||
|
if decision_for_entry:
|
||||||
|
chosen_option = next(
|
||||||
|
(c for c in choices if c.id == decision_for_entry.choice_id),
|
||||||
|
None
|
||||||
|
)
|
||||||
|
if chosen_option:
|
||||||
|
messages.append({"role": "user", "content": chosen_option.label})
|
||||||
return messages
|
return messages
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -120,10 +120,10 @@ def _make_service(db: AsyncSession) -> AdventureService:
|
||||||
|
|
||||||
|
|
||||||
async def _run_entry_pipeline_task(
|
async def _run_entry_pipeline_task(
|
||||||
adventure_id: uuid.UUID, entry_id: uuid.UUID
|
adventure_id: uuid.UUID, entry_id: uuid.UUID, user_id: uuid.UUID
|
||||||
) -> None:
|
) -> None:
|
||||||
async with AsyncSessionLocal() as db:
|
async with AsyncSessionLocal() as db:
|
||||||
await _make_service(db).run_entry_pipeline(adventure_id, entry_id)
|
await _make_service(db).run_entry_pipeline(adventure_id, entry_id, user_id)
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
@ -289,7 +289,7 @@ async def create_adventure(
|
||||||
)
|
)
|
||||||
await worker.enqueue(
|
await worker.enqueue(
|
||||||
partial(
|
partial(
|
||||||
_run_entry_pipeline_task, uuid.UUID(adventure.id), uuid.UUID(first_entry.id)
|
_run_entry_pipeline_task, uuid.UUID(adventure.id), uuid.UUID(first_entry.id), user_id
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return _to_adventure_response(adventure)
|
return _to_adventure_response(adventure)
|
||||||
|
|
@ -375,6 +375,7 @@ async def record_decision(
|
||||||
_run_entry_pipeline_task,
|
_run_entry_pipeline_task,
|
||||||
uuid.UUID(next_entry.adventure_id),
|
uuid.UUID(next_entry.adventure_id),
|
||||||
uuid.UUID(next_entry.id),
|
uuid.UUID(next_entry.id),
|
||||||
|
user_id,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return DecisionResponse(
|
return DecisionResponse(
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ class AdventureChoiceItem(BaseModel):
|
||||||
class AdventureEntryItem(BaseModel):
|
class AdventureEntryItem(BaseModel):
|
||||||
id: str
|
id: str
|
||||||
adventure_id: str
|
adventure_id: str
|
||||||
|
possible_choices: list[AdventureChoiceItem] | None
|
||||||
generated_from_choice_id: str | None
|
generated_from_choice_id: str | None
|
||||||
status: str
|
status: str
|
||||||
entry_index: int
|
entry_index: int
|
||||||
|
|
@ -81,6 +82,7 @@ async def get_adventure(
|
||||||
|
|
||||||
entries = await PostgresAdventureEntryRepository(db).list_for_adventure(adv_id)
|
entries = await PostgresAdventureEntryRepository(db).list_for_adventure(adv_id)
|
||||||
|
|
||||||
|
choices_repo = PostgresAdventureEntryChoiceRepository(db)
|
||||||
translation_repo = PostgresAdventureEntryTranslationRepository(db)
|
translation_repo = PostgresAdventureEntryTranslationRepository(db)
|
||||||
audio_repo = PostgresAdventureEntryAudioRepository(db)
|
audio_repo = PostgresAdventureEntryAudioRepository(db)
|
||||||
|
|
||||||
|
|
@ -93,10 +95,15 @@ async def get_adventure(
|
||||||
target_language=adventure.source_language,
|
target_language=adventure.source_language,
|
||||||
)
|
)
|
||||||
audio = await audio_repo.get_for_entry(entry_id=eid, component_type="story_text")
|
audio = await audio_repo.get_for_entry(entry_id=eid, component_type="story_text")
|
||||||
|
choices = await choices_repo.list_for_entry(eid)
|
||||||
entry_items.append(
|
entry_items.append(
|
||||||
AdventureEntryItem(
|
AdventureEntryItem(
|
||||||
id=entry.id,
|
id=entry.id,
|
||||||
adventure_id=entry.adventure_id,
|
adventure_id=entry.adventure_id,
|
||||||
|
possible_choices=[
|
||||||
|
AdventureChoiceItem(id=c.id, index=c.index, label=c.label, text=c.text)
|
||||||
|
for c in choices ]
|
||||||
|
if choices else None,
|
||||||
generated_from_choice_id=entry.generated_from_choice_id,
|
generated_from_choice_id=entry.generated_from_choice_id,
|
||||||
status=entry.status,
|
status=entry.status,
|
||||||
entry_index=entry.entry_index,
|
entry_index=entry.entry_index,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue