LLM 클라이언트 behaviour (SPEC §4). 코어는 LLM을 모른다 — 어댑터는 이 표면만 구현한다.
메시지는 프로바이더 중립 맵이다:
%{role: :user | :system, content: binary}%{role: :assistant, content: binary | nil, tool_calls: [tool_call]}%{role: :tool, tool_call_id: id, name: name, content: term}
실제 프로바이더 어댑터(Anthropic/OpenAI, Req + SSE)는 별도 패키지 el_graph_llm.
테스트에는 ElGraph.Test.ScriptedLLM을 쓴다.
Summary
Callbacks
대화를 모델에 보내고 다음 assistant 메시지를 받는다.
chat/3의 스트리밍 변형. 토큰이 도착하는 대로 opts[:on_delta](delta() 1-인자 fun)를
호출하고, 완료 시 chat/3과 동일한 누적 response()를 반환한다. 선택 콜백 — 모든
어댑터가 구현하지는 않는다(stream_supported?/1로 확인).
Functions
usage 누적 reducer — :usage 채널에 쓴다 (비용 가드, SPEC §4).
어댑터({module, config})가 스트리밍(stream_chat/3)을 지원하는지 확인한다.
노드에서 쓰는 스트리밍 헬퍼. stream_chat/3을 호출하되 도착하는 모든 델타를
ctx의 event_sink로 방출한다(ElGraph.Ctx.emit/2). 반환값은 stream_chat/3과 동일.
Types
@type delta() :: {:token, binary()} | {:tool_call_start, id :: String.t(), name :: String.t()} | {:tool_call_delta, id :: String.t(), args_fragment :: String.t()} | {:tool_call_end, id :: String.t()}
스트리밍 델타 이벤트 — on_delta 콜백이 받는다.
@type message() :: map()
@type usage() :: %{input_tokens: non_neg_integer(), output_tokens: non_neg_integer()}
Callbacks
@callback chat(config :: term(), messages :: [message()], opts :: keyword()) :: {:ok, response()} | {:error, term()}
대화를 모델에 보내고 다음 assistant 메시지를 받는다.
opts: :tools(tool 스펙 목록 — ElGraph.Action.to_tool_spec/1 형태),
:system 등 어댑터별 옵션.
@callback stream_chat(config :: term(), messages :: [message()], opts :: keyword()) :: {:ok, response()} | {:error, term()}
chat/3의 스트리밍 변형. 토큰이 도착하는 대로 opts[:on_delta](delta() 1-인자 fun)를
호출하고, 완료 시 chat/3과 동일한 누적 response()를 반환한다. 선택 콜백 — 모든
어댑터가 구현하지는 않는다(stream_supported?/1로 확인).
Functions
usage 누적 reducer — :usage 채널에 쓴다 (비용 가드, SPEC §4).
어댑터({module, config})가 스트리밍(stream_chat/3)을 지원하는지 확인한다.
@spec stream_to_ctx({module(), term()}, [message()], keyword(), ElGraph.Ctx.t()) :: {:ok, response()} | {:error, term()}
노드에서 쓰는 스트리밍 헬퍼. stream_chat/3을 호출하되 도착하는 모든 델타를
ctx의 event_sink로 방출한다(ElGraph.Ctx.emit/2). 반환값은 stream_chat/3과 동일.