ElGraph.LLM behaviour (ElGraph v0.3.0)

Copy Markdown View Source

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

Types

스트리밍 델타 이벤트 — on_delta 콜백이 받는다.

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

delta()

@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 콜백이 받는다.

message()

@type message() :: map()

response()

@type response() :: %{message: message(), usage: usage() | nil}

tool_call()

@type tool_call() :: %{id: String.t(), name: String.t(), args: map()}

usage()

@type usage() :: %{input_tokens: non_neg_integer(), output_tokens: non_neg_integer()}

Callbacks

chat(config, messages, opts)

@callback chat(config :: term(), messages :: [message()], opts :: keyword()) ::
  {:ok, response()} | {:error, term()}

대화를 모델에 보내고 다음 assistant 메시지를 받는다.

opts: :tools(tool 스펙 목록 — ElGraph.Action.to_tool_spec/1 형태), :system 등 어댑터별 옵션.

stream_chat(config, messages, opts)

(optional)
@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

add_usage(current, new)

@spec add_usage(usage(), usage() | nil) :: usage()

usage 누적 reducer — :usage 채널에 쓴다 (비용 가드, SPEC §4).

assistant(content, tool_calls \\ [])

@spec assistant(binary() | nil, [tool_call()]) :: message()

stream_supported?(arg)

@spec stream_supported?({module(), term()}) :: boolean()

어댑터({module, config})가 스트리밍(stream_chat/3)을 지원하는지 확인한다.

stream_to_ctx(arg, messages, opts, ctx)

@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과 동일.

tool_call(id, name, args)

@spec tool_call(String.t(), String.t(), map()) :: tool_call()

tool_result(tool_call_id, name, content)

@spec tool_result(String.t(), String.t(), term()) :: message()

user(content)

@spec user(binary()) :: message()