LangChain LangGraph LangSmith RAG Agent ... とは

# 問題

2025年2月現在LangChain `v0.3`
全くの無知識からだと種類が多すぎて訳が分からない

# [LangChain][1]

- ChatGPT等のLLMは種類が色々ある
- それぞれの使い方に微妙な違いがある

ものすごいざっくり言うとLLMへデータを送る、データを受け取るを共通化したwrapperのようなもの

https://www.youtube.com/watch?v=yF9kGESAi3M

v0.2で古いが、参考にはなった

https://www.youtube.com/playlist?list=PLqZXAkvF1bPNQER9mLmDbntNfSpzdDIU5

これも古いが、参考にはなった

https://www.youtube.com/@mathbullet/videos

この人達はよく分かってる人と全く知識のない人とで一緒にやっていくので、よく分かってないこっちの気持ちを代弁してくれる感じで分かりやすい

## [LangChain Expression Language (LCEL)][14]

linuxのコマンドで使える「|」と同じような役割、書き方で`prompt -> llm -> output`みたいな一連の流れを`chain`として一体化させて、invoke出来るという仕組み

## tool

[通常LLMはtool_callingが出来る][18]

手順としては

1. LLMに`bind_tools`して関数等をtoolとして渡しておく
1. toolにはdocstring等でLLMに詳しくどう言うものかを説明しておく
1. LLMに問い合わせた際に適切にtoolを使ってもらうように説明しておく
1. そうすることで適切にtoolを使って回答してくれる

例えばLLMだけでは分からない社内の情報はRAGやデータベースに保存されているので、そういう質問の場合はtoolを使って回答するとか
どのtoolへどういうパラメーターを使うかはLLM次第

https://python.langchain.com/docs/integrations/chat/#featured-providers


[API][2]を細かく見ると更に

- Core
- Langchain
- Text Splitters
- Community
- Experimental

などがある

## Core

LangChainの本質的な部分のみ切り出したもの

## Langchain

とりあえずこれさえimportしておけば全部あるバージョン？

## Text Splitters

RAG等で処理したいテキストデータが大量すぎる場合に、処理しやすい単位で切り分ける必要がある
そういう時のためのもの

## Community

サードパーティー用などその他細々したもの（特に使った事がないのでよく分からない）

## Experimental

名前の通り


# LangGraph

ある種の[ステートマシーン][3]
LangChainを元にnode作ってedgeで繋いで...をコードで書くので、パッと見分かりにくいと評判
その内Xstateみたいにdictで表現できればいいなと思うけけど

https://academy.langchain.com/

でLangGraphの無料コースがある（約6時間）

# LangGraph Studio

視覚的にLangGraphを動かせるIDE
現状LangGraphを視覚的に操作できるだけで、graphの編集機能はないと思う
[Xstateのvisualizer][4]に似てる

# LangSmith

LangChain、LangGraphが複雑になる程に何がどうしてこうなったのか？とわからなくなるので、printデバッグ以外のトレーサーが必要になる
それがLangSmith

# RAG

簡単に言うと検索できる外部記憶
結局LLMへ送信できるトークン数には上限があるので専門的な知識を全部渡して理解してもらおうとするには限度がある
なので、事前処理した（documentをembeddingしてvector storeに保存）データを元に、LLMへ投げる前に検索しておいて、LLMへ主要な部分だけを質問内容に繋げて聞くという手法

RAGはまだ成熟中のようで、どう言うchunkでembeddingした方が良いのかとか、Graph RAGとかAgentic RAGとか色々手探りな状況っぽい
その内LLMへ投げるトークン数が飛躍的に上がって、料金も下がる（又はローカルでも十分に動かせる）とかになればRAGは要らない？

> なんとなく近い将来は専門知識を事前にトレーニングさせたプライベートなLLMを個別に持っておいて（ローカルなのかサービスとしてなのか）、その時々に適切なLLMを使うっていう感じになりそうだけど

# AI Agent

LangGraphを組み上げていって、半自動で動くエージェントのようなものに仕立て上げたものって感じ

## [Human in the loop (HITL)][15]

https://langchain-ai.github.io/langgraph/how-tos/human_in_the_loop/wait-user-input/

特定の処理で人間にその場で処理の判断を委ねる場合に使う

- interruptで人間側に処理の判断を委ねる
- Commandで人間の回答を返す

## [Functional API][16]

LangGraphってもっさりして書きにくいし読みにくいよねを解消するβ版

## memory

![Untitled-2022-09-16-1522.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16757/4998cab5-a8ef-b1c9-1580-9aff6e62878f.png)


結局生のLLMはトレーニングした状態しか保持しておらず、毎度の問い合わせはstatelessなので、事前に聞いた事は何も考慮してくれない
（HTTPサーバーにcookieなしでアクセスしてるようなもの）

Agentまでくると事前に聞いた内容などを保持しておいて、それら過去の内容と合わせて回答を貰えるようにしたい、のでこれら以降のmemoryの使い分けが必要になる


### Short term memory

StateやCheckpointが通常使われる

#### State

Agentみたいなものまででもなく普通にLangGraph（state machineとして）利用時には使うが、Xstateで言う所のcontextであり、LLMとのmessageを保存しておいたり、LLMとの会話で出てきた結果で重要なことを保存したりだとか
何を保存するかは自由

###### [reducer][6]

Stateを保存する際に各要素をどのように更新していくのかを決めるもの

例：

- [add_messages][19]
    - listにmessageを通常は簡単にappendする
    - [RemoveMessageをID付きで渡すと][7]そのmessageをlistから消してくれる
- [operator][5].add
    - 一般的なlistへのappendとしてのaddだったり、要は+演算子で出来ること
- などで、独自に作ることも出来る
  > Module 2 - Lesson 2: State Reducers
  > https://academy.langchain.com/



##### MessagesState

LLMへのmessageは通常保存しておくものなので[MessagesState][12]が用意されている
これはadd_messagesをreducerとしているので、どんどん追記していく
なので、会話を続ければ続ける程流すトークン数が増えていく（最初からの会話を全部流すので）

やり方は色々あるんだろうけど、例えば10件messageが溜まったのならその10件をLLMへ投げて一旦summaryとして要約してもらい、その10件はmessagesから消して次回の問い合わせはsummary + messagesとか工夫が必要
* summaryにするので情報は一部削られる事になる

> Module2 - Lesson 5: Chatbot w/ Summarizing Messages and Memory
に例が出てくる
> https://academy.langchain.com/


> トークン数の上限がなくなるとか、ローカルで十分耐えれるLLMが動かせるとかになればこういう工夫も要らなくなりそう




#### Checkpoint

Stateの履歴のようなもの
Stateへの**状態が変わる度に**それらをcheckpointとして保存しておいてくれて、例え同プロセスでなくても同じthread-idなら同じ情報が引き出せるし、過去のあるpointへ戻って再度LLMへ問い合わせたりとか出来る

* 必ず[thread_id][8]を指定して使う必要がある
* [InMemorySaver][9]は開発時にサラッと簡単に使うため
* 小規模なら[SqliteSaver][10]
* 一般的には[PostgresSaver][11]


### Long term memory

![Untitled-2022-09-16-1522x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16757/86754bb0-2c16-13b0-02f8-5c0d5c457092.png)


- Checkpointerはthread単位の保存
- Long termはuser単位の保存

threadはある一定の会話（話題）についての長期的な保存であり、threadで出てきた内容で長期的に、且つ別threadでも使いたい情報（ユーザーの氏名とか住所とか）がある場合にこれを使う
* thread間で同じ情報を共有したい場合の要はデータベース


InMemoryStore（開発時）とかPostgresStoreを使う

[長期記憶のコンセプト][13]として3つに分けられ

- Semantic
- Episodic
- Procedural

こういう概念で保存していくと良いよ的な話が書いてある

### [Trustcall][20]

Module 5 - Lesson 4: Memory Schema + Collection

https://academy.langchain.com/

LLMには`.with_structured_output()`で定義したデータ型で返答してもらうように頼めるが、そのデータ型が複雑な場合はちゃんと処理できずに終わってしまう
これを解決するのがTrustcall

LLMに問い合わせる際にJSON丸ごとで返してと言わずに、JSONのpatch（差分）で返してくれといい具合に問い合わせてpatchを当てた最終的なJSONデータをstructured_outputとしてTrustcallが返してくれるようなイメージ



# まとめ

全体的に使いこなせればすごいけど、まだv0.3とか0.2辺りで仕様変更も多いし（[productionで使ってるところもある][17]らしいけど）、ライブラリ群の構成がゴロゴロ変わってるし、1ヶ月単位で追いつかないといけないぐらい
ちょっと古い情報を見てると全然違ったりするのでimportするだけでも大変



[1]: https://python.langchain.com/docs/introduction/
[2]: https://python.langchain.com/api_reference/
[3]: https://ja.wikipedia.org/wiki/%E6%9C%89%E9%99%90%E3%82%AA%E3%83%BC%E3%83%88%E3%83%9E%E3%83%88%E3%83%B3
[4]: https://stately.ai/viz
[5]: https://docs.python.org/ja/3.13/library/operator.html
[6]: https://langchain-ai.github.io/langgraph/concepts/low_level/#default-reducer
[7]: https://langchain-ai.github.io/langgraph/how-tos/memory/delete-messages/
[8]: https://langchain-ai.github.io/langgraph/concepts/persistence/
[9]: https://langchain-ai.github.io/langgraph/reference/checkpoints/#langgraph.checkpoint.memory.InMemorySaver
[10]: https://langchain-ai.github.io/langgraph/reference/checkpoints/#langgraph.checkpoint.sqlite.SqliteSaver
[11]: https://langchain-ai.github.io/langgraph/reference/checkpoints/#langgraph.checkpoint.postgres.PostgresSaver
[12]: https://langchain-ai.github.io/langgraph/concepts/low_level/#messagesstate
[13]: https://langchain-ai.github.io/langgraph/concepts/memory/?h=long+term#memory-types
[14]: https://python.langchain.com/docs/concepts/lcel/
[15]: https://langchain-ai.github.io/langgraph/concepts/human_in_the_loop/
[16]: https://langchain-ai.github.io/langgraph/concepts/functional_api/#example
[17]: https://blog.langchain.dev/is-langgraph-used-in-production/
[18]: https://python.langchain.com/docs/integrations/chat/#featured-providers
[19]: https://langchain-ai.github.io/langgraph/reference/graphs/?h=add+messages#langgraph.graph.state.CompiledStateGraph.ainvoke
[20]: https://github.com/hinthornw/trustcall
[21]: https://python.langchain.com/docs/how_to/structured_output/