176 lines
4.9 KiB
Python
176 lines
4.9 KiB
Python
from typing import Annotated, Literal, TypedDict
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
from wf_authoring.schemas import state_field
|
|
from wf_core.models.reducers import ReducerRef
|
|
|
|
|
|
class SophisticatedRates(TypedDict):
|
|
r_1: float
|
|
r_10: float
|
|
r_80: float # 0.5 sometimes, 1
|
|
# not including 240 because ill force it by simple_counter, the pool split probably forces half, dealing w ts is ahh.
|
|
r_240: float # i caved
|
|
|
|
|
|
# i copy things over, not the greatest design but im not doing deep fixes.
|
|
|
|
|
|
class SophisticatedCounter(TypedDict):
|
|
c_10: Annotated[
|
|
int,
|
|
state_field(
|
|
reducer=ReducerRef(name="wf.std.modulo_add", config={"modulus": 10})
|
|
),
|
|
] # add!
|
|
c_80: Annotated[
|
|
int,
|
|
state_field(
|
|
reducer=ReducerRef(name="wf.std.modulo_add", config={"modulus": 80})
|
|
),
|
|
]
|
|
# all that reducerref and then nothing touches them. only way you do rn is
|
|
# putting in/out maps on graph.use, which is cool ig. i just am not using them.
|
|
|
|
|
|
class Counters(BaseModel):
|
|
# alot of state["thing"] in the og code, so i think this is the design?
|
|
counter: SophisticatedCounter = Field(
|
|
default_factory=lambda: SophisticatedCounter(c_10=0, c_80=0)
|
|
) # or, that is because of langgraph limitation,
|
|
# id prefer counter.update with dict.update override (Overwrite, not like that ever worked)
|
|
simple_counter: Annotated[int, state_field(reducer="wf.std.add")] # add
|
|
|
|
|
|
class Countdown(BaseModel):
|
|
countdown: Annotated[int, state_field(reducer="wf.std.add")] # add!
|
|
|
|
|
|
# has to migrate from typeddict for what? for nothing.
|
|
class Context(TypedDict): # dataclass support? no. i mean langgraph doesnt.
|
|
"custom RuntimeContext[MyContext] support?"
|
|
|
|
pool: UnsophisticatedPool
|
|
initial_rates: SophisticatedRates
|
|
type: Literal["banner", "normal"]
|
|
"still very convoluted logic"
|
|
|
|
|
|
# class Input(TypedDict, total=False):
|
|
|
|
|
|
## context is a hard thing
|
|
# According to https://docs.langchain.com/oss/python/concepts/context, there are three types:
|
|
#
|
|
# | type | mut | lifetime |
|
|
# | --- | --- | --- |
|
|
# |static runtime (context) | static | single run |
|
|
# |dynamic runtime (state) | mut | single run |
|
|
# |dynamic cross-convo (store) | mut | cross-conversation |
|
|
#
|
|
# now what the hell is store
|
|
### store
|
|
#
|
|
# store is used in langgraph-demo for debugging. but it can be used for more things.
|
|
# it saves every turn. every graph nodes. I use InMemoryStore, you can use psql store!
|
|
# This allows for picking the work up again after a while for example.
|
|
# a lot more versatility there.
|
|
#
|
|
### what about us? how should we handle context?
|
|
#
|
|
# in the future if wed like, we could handle context. This could be useful for lda.chat!
|
|
# i want lda.chat to be/have a meta-agent. So i could spin up ideas! a
|
|
|
|
|
|
class ContextInput(BaseModel):
|
|
context: Context # final!
|
|
|
|
|
|
class how_do_i_explain_this(BaseModel):
|
|
pity_120_available: bool = Field(default=True)
|
|
|
|
|
|
class Input(Counters, ContextInput, Countdown, how_do_i_explain_this):
|
|
"input of the graph"
|
|
|
|
|
|
# countdown: int
|
|
# simple_counter: int
|
|
# counter: SophisticatedCounter
|
|
|
|
# context: Context
|
|
|
|
|
|
class Entity(TypedDict):
|
|
category: Literal["1", "10", "80", "240"]
|
|
name: str
|
|
|
|
|
|
class PoolByCategory(TypedDict):
|
|
pool: list[str]
|
|
category: Literal["1", "10", "80", "240"] # stricter types
|
|
rates: float
|
|
|
|
|
|
# context outside? what is input?
|
|
class UnsophisticatedPool(TypedDict):
|
|
n_1: list[str]
|
|
n_10: list[str]
|
|
n_80: list[str] # normal + limited
|
|
n_240: list[str] # special... have to do this
|
|
|
|
|
|
class Storage(BaseModel):
|
|
"i NEED to do this?"
|
|
|
|
storage: Annotated[list[Entity], state_field(reducer="wf.std.append")] = Field(
|
|
default_factory=list
|
|
) # add!
|
|
|
|
|
|
class CurrentRoll(BaseModel):
|
|
this: Entity
|
|
|
|
|
|
class PartialRates(SophisticatedRates, TypedDict, total=False):
|
|
pass
|
|
|
|
|
|
class Rates(BaseModel):
|
|
rates: Annotated[PartialRates, state_field(reducer="wf.std.merge_object")] # or_!
|
|
|
|
|
|
class CurrentPools(BaseModel):
|
|
current_pools: list[PoolByCategory] # replace!
|
|
|
|
|
|
# holy refactory
|
|
class State(
|
|
Counters,
|
|
ContextInput,
|
|
Countdown,
|
|
CurrentRoll,
|
|
Storage,
|
|
Rates,
|
|
CurrentPools,
|
|
how_do_i_explain_this,
|
|
):
|
|
"this forces basemodel, i used typeddict"
|
|
|
|
|
|
# this feels fragmented. it is fragmented
|
|
|
|
# countdown: int # input carries here, should input have a bound like all(attr(input) in attr(state))? how tf do i even try to type that
|
|
# simple_counter: int # how to signal that ts adds up? we have that.
|
|
# counter: SophisticatedCounter
|
|
# rates: SophisticatedRates # ts needs reworking
|
|
# current_pools: list[PoolByCategory]
|
|
# this: Entity
|
|
# storage: list[
|
|
# Entity # how do we convey "add" root level? Annotated again? what pydantic shit can give this thing the metadata it neeeds.
|
|
# ] # maybe for the 120 check we need to add some if any(entity.category = "240" for entity in storage), WHICH IS ASS btw.
|
|
|
|
# fuck this yo
|
|
# context: Context
|