LangChain
https://gyazo.com/82275023cd8048d52a5ca0c2a5dea114
なくていいっしょ派だけど text_splitter とかは使いたい、一度触っておく
community
QuickStart
page_content, metadata
ここの stuff は詰める staff やね
コンポーネント
LLMs
ChatModels
callbacks に渡す、標準出力に出すだけやろと思うがフィルタが色々ある
template_format= に jinja2 や mustache がある
description に書いた説明がプロンプトに使われる? 例を見たい → たぶんこれ parser.get_format_instructions()
Document Loaders
epub も pandoc で markdown にして Header で割ったほうがいいような wikipedia, Vertex AI Search, Elasticsearch 等もここ
ユーザ入力(質問)から LLM に検索すべき単語を取り出したり言い換えをやらせる
Chains
LCEL
| で繋いでいくやつ何?
Runnable が実体
| は Python の __or__ 呼び出しになっている / 右から作用する __ror__ のいずれかが呼ばれて DSL になっている
へーとなるものの、まあこういう型になってダルいやろな
コンポーネントごとに入出力の型がきまってる input_schema / output_schema
ためになる
RunnableLambda / RunnableGenerator
| で繋いだ結果できるのが RunnableSequence
dict をつなぐとキーごとの Runnable をくっつけた RunnablePararell になる
chain.get_graph().print_ascii() で AA で可視化できる
RunnablePassthrough.assign(mult=lambda x: x["num"] * 3) で値を追加
入力と最終的な出力両方ほしい時、変なことせずchain を分ければ良い
code:pararell
chain = RunnableParallel(
{
"input": RunnablePassThrough(),
"output": RunnablePathThrough() | template | llm | parser | ...
}
)
debug
code:debug.py
from langchain.globals import set_debug, set_verbose
set_debug(True)
set_verbose(True)
ほかに globals にあるのはキャッシュぐらい
これも大抵書いてる
code:logging.py
import logging
import sys
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG, force=True)
Loader
Directory Loader と組み合わせる
ヘッダ無い時とかどういう感じになるのかな?
なんか使いづれえな
isa TextSplitter じゃないし
一旦無視
epub 読みたい
CustomRetriever 作る
メモリ上の DataFrame から id の前後取ってくる
code:dfretriever.py
from langchain_core.documents import Document
from langchain_core.retrievers import BaseRetriever
class DataFrameRetriever(BaseRetriever):
"""id から前後のテキストを取得する Retriever"""
segments: pd.DataFrame
lead: int = 5
lag: int = 5
def _get_relevant_documents(self, id_: str) -> listDocument: item = self.segments[self.segments"id" == id_] if item.empty:
return []
(idx,) = item.index
return [Document(r"text", metadata=r) for _, r in view.iterrows()] Callback
独自のコールバックを作って chain の途中に挟んで print debug できる
Stream で動作するものは AsyncCallbackHandler 使う、stream で呼んでも prompt などは Base が発火する
code:print_callback.py
from langchain_core.callbacks import BaseCallbackHandler
class PrintCallback(BaseCallbackHandler):
def on_chain_end(self, outputs, **kwargs):
print(outputs)
chain = (
...
)
usage_metadata を取得する Callback
chat でも取るなら on_chain_end 見るしかない?
動作確認してないがまあこういう雰囲気で
* ignore_chain などのattribute 試す code:usage_metadata.py
from langchain_core.callbacks import BaseCallbackHandler
from langchain_core.messages.ai import AIMessage, UsageMetadata
class TokenUsageCallback(BaseCallbackHandler):
def __init__(self) -> None:
super().__init__()
self.total_usage = UsageMetadata(
input_tokens=0, output_tokens=0, total_tokens=0
)
def add_usage(self, usage: UsageMetadata) -> None:
def on_chain_end(self, outputs, **kwargs) -> None:
inputs = kwargs.get("inputs", None)
if isinstance(inputs, AIMessage) and inputs.usage_metadata is not None:
self.add_usage(inputs.usage_metadata)
usage = TokenUsageCallback()
for chunk ik chain.stream(input, {"callbacks": usage}): ...
print(usage.total_usage)
vectorstore に metadata も保存するには? / 検索時に指定するには?
community なのかそうじゃないのか
from langchain.vectorstores import LanceDB
from langchain_community.vectorstores import LanceDB
どっちやねん
はい...
community のほうがコードジャンプも効く
はよリリースしろや、いつまで Gemini 1.5 使わせないねん
embed_query / embed_document でちゃんと Task 切り替えてるのは当然だけど偉いね期待に届いているよ
OutputParser
使い方いろいろすぎないか
output_parser.get_format_instructions() すると csv で出力してねという文言が返るのでプロンプトに入れる...素朴
JSON Output Parser なら JSON Schema が出てくる
英語でいいのか問題
Chainlit
Need type annotation for "chain" 言われたら
Runnbale か RunnableSerializable かなあ
code:annotation_for_chain.py
from langchain_core.runnables import Runnable
chain: Runnable = {"question": RunnablePassthrough()} | ...
hub
プロンプトやチェーンの共有
code:pull.py
from langchain import hub
hub.pull(...)
Gemini
code:llm.py
import vertexai
vertexai.init(project="pokutuna-playground", location="asia-northeast1")
from langchain.llms import VertexAI
llm = VertexAI(model_name="gemini-pro", temperature=0)
llm("What is BigQuery?")
これだけだと嬉しさないが
2024/10/4 VertexAI 機能置いていかれがちなので ChatVertexAI 使うほうが大抵良い...
SystemMessage とか意味あるの? と思ったけど最初の SystemMessage は API の system_instruction にマップされる
with_structured_output はどうやっている?
llm = self.bind_tools([schema], tool_choice="any") している
include_raw
テストでいい感じにモックするには