mirror of
https://github.com/langchain-ai/learning-langchain.git
synced 2026-07-01 16:06:32 -04:00
fix ch4 to ch8
This commit is contained in:
@@ -3,9 +3,10 @@ import {
|
||||
Annotation,
|
||||
messagesStateReducer,
|
||||
START,
|
||||
} from "@langchain/langgraph";
|
||||
import { ChatOpenAI } from "@langchain/openai";
|
||||
import { HumanMessage } from "@langchain/core/messages";
|
||||
END,
|
||||
} from '@langchain/langgraph';
|
||||
import { ChatOpenAI } from '@langchain/openai';
|
||||
import { HumanMessage } from '@langchain/core/messages';
|
||||
|
||||
const State = {
|
||||
messages: Annotation({
|
||||
@@ -23,14 +24,14 @@ async function chatbot(state) {
|
||||
return { messages: answer };
|
||||
}
|
||||
|
||||
builder = builder.addNode("chatbot", chatbot);
|
||||
builder = builder.addNode('chatbot', chatbot);
|
||||
|
||||
builder = builder.addEdge(START, "chatbot").addEdge("chatbot", END);
|
||||
builder = builder.addEdge(START, 'chatbot').addEdge('chatbot', END);
|
||||
|
||||
let graph = builder.compile();
|
||||
|
||||
// Run the graph
|
||||
const input = { messages: [new HumanMessage("hi!")] };
|
||||
const input = { messages: [new HumanMessage('hi!')] };
|
||||
for await (const chunk of await graph.stream(input)) {
|
||||
console.log(chunk);
|
||||
}
|
||||
|
||||
+24
-12
@@ -3,27 +3,39 @@ import {
|
||||
SystemMessage,
|
||||
AIMessage,
|
||||
filterMessages,
|
||||
} from "@langchain/core/messages";
|
||||
} from '@langchain/core/messages';
|
||||
|
||||
const messages = [
|
||||
new SystemMessage({ content: "you are a good assistant", id: "1" }),
|
||||
new HumanMessage({ content: "example input", id: "2", name: "example_user" }),
|
||||
new SystemMessage({ content: 'you are a good assistant', id: '1' }),
|
||||
new HumanMessage({ content: 'example input', id: '2', name: 'example_user' }),
|
||||
new AIMessage({
|
||||
content: "example output",
|
||||
id: "3",
|
||||
name: "example_assistant",
|
||||
content: 'example output',
|
||||
id: '3',
|
||||
name: 'example_assistant',
|
||||
}),
|
||||
new HumanMessage({ content: "real input", id: "4", name: "bob" }),
|
||||
new AIMessage({ content: "real output", id: "5", name: "alice" }),
|
||||
new HumanMessage({ content: 'real input', id: '4', name: 'bob' }),
|
||||
new AIMessage({ content: 'real output', id: '5', name: 'alice' }),
|
||||
];
|
||||
|
||||
// Filter for human messages
|
||||
filterMessages(messages, { includeTypes: ["human"] });
|
||||
const filterByHumanMessages = filterMessages(messages, {
|
||||
includeTypes: ['human'],
|
||||
});
|
||||
console.log(`Human messages: ${JSON.stringify(filterByHumanMessages)}`);
|
||||
|
||||
// Filter to exclude names
|
||||
filterMessages(messages, {
|
||||
excludeNames: ["example_user", "example_assistant"],
|
||||
const filterByExcludedNames = filterMessages(messages, {
|
||||
excludeNames: ['example_user', 'example_assistant'],
|
||||
});
|
||||
console.log(
|
||||
`\nExcluding example names: ${JSON.stringify(filterByExcludedNames)}`
|
||||
);
|
||||
|
||||
// Filter by types and IDs
|
||||
filterMessages(messages, { includeTypes: ["human", "ai"], excludeIds: ["3"] });
|
||||
const filterByTypesAndIDs = filterMessages(messages, {
|
||||
includeTypes: ['human', 'ai'],
|
||||
excludeIds: ['3'],
|
||||
});
|
||||
console.log(
|
||||
`\nFiltered by types and IDs: ${JSON.stringify(filterByTypesAndIDs)}`
|
||||
);
|
||||
|
||||
@@ -3,22 +3,23 @@ import {
|
||||
SystemMessage,
|
||||
AIMessage,
|
||||
mergeMessageRuns,
|
||||
} from "@langchain/core/messages";
|
||||
} from '@langchain/core/messages';
|
||||
|
||||
const messages = [
|
||||
new SystemMessage("you're a good assistant."),
|
||||
new SystemMessage("you always respond with a joke."),
|
||||
new SystemMessage('you always respond with a joke.'),
|
||||
new HumanMessage({
|
||||
content: [{ type: "text", text: "i wonder why it's called langchain" }],
|
||||
content: [{ type: 'text', text: "i wonder why it's called langchain" }],
|
||||
}),
|
||||
new HumanMessage("and who is harrison chasing anyways"),
|
||||
new HumanMessage('and who is harrison chasing anyways'),
|
||||
new AIMessage(
|
||||
'Well, I guess they thought "WordRope" and "SentenceString" just didn\'t have the same ring to it!',
|
||||
'Well, I guess they thought "WordRope" and "SentenceString" just didn\'t have the same ring to it!'
|
||||
),
|
||||
new AIMessage(
|
||||
"Why, he's probably chasing after the last cup of coffee in the office!",
|
||||
"Why, he's probably chasing after the last cup of coffee in the office!"
|
||||
),
|
||||
];
|
||||
|
||||
// Merge consecutive messages
|
||||
mergeMessageRuns(messages);
|
||||
const mergedMessages = mergeMessageRuns(messages);
|
||||
console.log(mergedMessages);
|
||||
|
||||
+8
-8
@@ -1,13 +1,13 @@
|
||||
import {
|
||||
StateGraph,
|
||||
StateType,
|
||||
Annotation,
|
||||
messagesStateReducer,
|
||||
START,
|
||||
} from "@langchain/langgraph";
|
||||
END,
|
||||
} from '@langchain/langgraph';
|
||||
|
||||
import { ChatOpenAI } from "@langchain/openai";
|
||||
import { HumanMessage } from "@langchain/core/messages";
|
||||
import { ChatOpenAI } from '@langchain/openai';
|
||||
import { HumanMessage } from '@langchain/core/messages';
|
||||
|
||||
const model = new ChatOpenAI();
|
||||
|
||||
@@ -28,14 +28,14 @@ async function chatbot(state) {
|
||||
}
|
||||
|
||||
const builder = new StateGraph(State)
|
||||
.addNode("chatbot", chatbot)
|
||||
.addEdge(START, "chatbot")
|
||||
.addEdge("chatbot", END);
|
||||
.addNode('chatbot', chatbot)
|
||||
.addEdge(START, 'chatbot')
|
||||
.addEdge('chatbot', END);
|
||||
|
||||
const graph = builder.compile();
|
||||
|
||||
// Example usage
|
||||
const input = { messages: [new HumanMessage("hi!")] };
|
||||
const input = { messages: [new HumanMessage('hi!')] };
|
||||
for await (const chunk of await graph.stream(input)) {
|
||||
console.log(chunk);
|
||||
}
|
||||
|
||||
+20
-20
@@ -1,17 +1,17 @@
|
||||
import { DuckDuckGoSearch } from "@langchain/community/tools/duckduckgo_search";
|
||||
import { Calculator } from "@langchain/community/tools/calculator";
|
||||
import { ChatOpenAI } from "@langchain/openai";
|
||||
import { OpenAIEmbeddings } from "@langchain/openai";
|
||||
import { Document } from "@langchain/core/documents";
|
||||
import { MemoryVectorStore } from "@langchain/community/vectorstores/memory";
|
||||
import { DuckDuckGoSearch } from '@langchain/community/tools/duckduckgo_search';
|
||||
import { Calculator } from '@langchain/community/tools/calculator';
|
||||
import { ChatOpenAI } from '@langchain/openai';
|
||||
import { OpenAIEmbeddings } from '@langchain/openai';
|
||||
import { Document } from '@langchain/core/documents';
|
||||
import { MemoryVectorStore } from 'langchain/vectorstores/memory';
|
||||
import {
|
||||
StateGraph,
|
||||
Annotation,
|
||||
messagesStateReducer,
|
||||
START,
|
||||
} from "@langchain/langgraph";
|
||||
import { ToolNode, toolsCondition } from "@langchain/langgraph/prebuilt";
|
||||
import { HumanMessage } from "@langchain/core/messages";
|
||||
} from '@langchain/langgraph';
|
||||
import { ToolNode, toolsCondition } from '@langchain/langgraph/prebuilt';
|
||||
import { HumanMessage } from '@langchain/core/messages';
|
||||
|
||||
const search = new DuckDuckGoSearch();
|
||||
const calculator = new Calculator();
|
||||
@@ -27,9 +27,9 @@ const toolsStore = await MemoryVectorStore.fromDocuments(
|
||||
new Document({
|
||||
pageContent: tool.description,
|
||||
metadata: { name: tool.constructor.name },
|
||||
}),
|
||||
})
|
||||
),
|
||||
embeddings,
|
||||
embeddings
|
||||
);
|
||||
const toolsRetriever = toolsStore.asRetriever();
|
||||
|
||||
@@ -40,7 +40,7 @@ const annotation = Annotation.Root({
|
||||
|
||||
async function modelNode(state) {
|
||||
const selectedTools = tools.filter((tool) =>
|
||||
state.selected_tools.includes(tool.constructor.name),
|
||||
state.selected_tools.includes(tool.constructor.name)
|
||||
);
|
||||
const res = await model.bindTools(selectedTools).invoke(state.messages);
|
||||
return { messages: res };
|
||||
@@ -55,13 +55,13 @@ async function selectTools(state) {
|
||||
}
|
||||
|
||||
const builder = new StateGraph(annotation)
|
||||
.addNode("select_tools", selectTools)
|
||||
.addNode("model", modelNode)
|
||||
.addNode("tools", new ToolNode(tools))
|
||||
.addEdge(START, "select_tools")
|
||||
.addEdge("select_tools", "model")
|
||||
.addConditionalEdges("model", toolsCondition)
|
||||
.addEdge("tools", "model");
|
||||
.addNode('select_tools', selectTools)
|
||||
.addNode('model', modelNode)
|
||||
.addNode('tools', new ToolNode(tools))
|
||||
.addEdge(START, 'select_tools')
|
||||
.addEdge('select_tools', 'model')
|
||||
.addConditionalEdges('model', toolsCondition)
|
||||
.addEdge('tools', 'model');
|
||||
|
||||
const graph = builder.compile();
|
||||
|
||||
@@ -69,7 +69,7 @@ const graph = builder.compile();
|
||||
const input = {
|
||||
messages: [
|
||||
new HumanMessage(
|
||||
"How old was the 30th president of the United States when he died?",
|
||||
'How old was the 30th president of the United States when he died?'
|
||||
),
|
||||
],
|
||||
};
|
||||
|
||||
+19
-16
@@ -2,15 +2,15 @@ import {
|
||||
AIMessage,
|
||||
SystemMessage,
|
||||
HumanMessage,
|
||||
} from "@langchain/core/messages";
|
||||
import { ChatOpenAI } from "@langchain/openai";
|
||||
} from '@langchain/core/messages';
|
||||
import { ChatOpenAI } from '@langchain/openai';
|
||||
import {
|
||||
StateGraph,
|
||||
Annotation,
|
||||
messagesStateReducer,
|
||||
START,
|
||||
END,
|
||||
} from "@langchain/langgraph";
|
||||
} from '@langchain/langgraph';
|
||||
|
||||
const model = new ChatOpenAI();
|
||||
|
||||
@@ -21,7 +21,7 @@ const annotation = Annotation.Root({
|
||||
const generatePrompt = new SystemMessage(
|
||||
`You are an essay assistant tasked with writing excellent 3-paragraph essays.
|
||||
Generate the best essay possible for the user's request.
|
||||
If the user provides critique, respond with a revised version of your previous attempts.`,
|
||||
If the user provides critique, respond with a revised version of your previous attempts.`
|
||||
);
|
||||
|
||||
async function generate(state) {
|
||||
@@ -31,7 +31,7 @@ async function generate(state) {
|
||||
|
||||
const reflectionPrompt = new SystemMessage(
|
||||
`You are a teacher grading an essay submission. Generate critique and recommendations for the user's submission.
|
||||
Provide detailed recommendations, including requests for length, depth, style, etc.`,
|
||||
Provide detailed recommendations, including requests for length, depth, style, etc.`
|
||||
);
|
||||
|
||||
async function reflect(state) {
|
||||
@@ -58,16 +58,16 @@ function shouldContinue(state) {
|
||||
// End after 3 iterations, each with 2 messages
|
||||
return END;
|
||||
} else {
|
||||
return "reflect";
|
||||
return 'reflect';
|
||||
}
|
||||
}
|
||||
|
||||
const builder = new StateGraph(annotation)
|
||||
.addNode("generate", generate)
|
||||
.addNode("reflect", reflect)
|
||||
.addEdge(START, "generate")
|
||||
.addConditionalEdges("generate", shouldContinue)
|
||||
.addEdge("reflect", "generate");
|
||||
.addNode('generate', generate)
|
||||
.addNode('reflect', reflect)
|
||||
.addEdge(START, 'generate')
|
||||
.addConditionalEdges('generate', shouldContinue)
|
||||
.addEdge('reflect', 'generate');
|
||||
|
||||
const graph = builder.compile();
|
||||
|
||||
@@ -75,15 +75,18 @@ const graph = builder.compile();
|
||||
const initialState = {
|
||||
messages: [
|
||||
new HumanMessage(
|
||||
"Write an essay about the relevance of 'The Little Prince' today.",
|
||||
"Write an essay about the relevance of 'The Little Prince' today."
|
||||
),
|
||||
],
|
||||
};
|
||||
|
||||
for await (const output of graph.stream(initialState)) {
|
||||
for await (const output of await graph.stream(initialState)) {
|
||||
const messageType = output.generate ? 'generate' : 'reflect';
|
||||
console.log(
|
||||
"\nNew message:",
|
||||
output.messages[output.messages.length - 1].content.slice(0, 100),
|
||||
"...",
|
||||
'\nNew message:',
|
||||
output[messageType].messages[
|
||||
output[messageType].messages.length - 1
|
||||
].content.slice(0, 100),
|
||||
'...'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { StateGraph, START, Annotation } from "@langchain/langgraph";
|
||||
import { StateGraph, START, Annotation } from '@langchain/langgraph';
|
||||
|
||||
const StateAnnotation = Annotation.Root({
|
||||
foo: Annotation(), // string type
|
||||
@@ -13,22 +13,23 @@ const SubgraphStateAnnotation = Annotation.Root({
|
||||
const subgraphNode = async (state) => {
|
||||
// note that this subgraph node can communicate with
|
||||
// the parent graph via the shared "foo" key
|
||||
return { foo: state.foo + "bar" };
|
||||
return { foo: state.foo + 'bar' };
|
||||
};
|
||||
|
||||
const subgraph = new StateGraph(SubgraphStateAnnotation)
|
||||
.addNode("subgraph", subgraphNode)
|
||||
.addNode('subgraph', subgraphNode)
|
||||
.addEdge(START, 'subgraph')
|
||||
// Additional subgraph setup would go here
|
||||
.compile();
|
||||
|
||||
// Define parent graph
|
||||
const parentGraph = new StateGraph(StateAnnotation)
|
||||
.addNode("subgraph", subgraph)
|
||||
.addEdge(START, "subgraph")
|
||||
.addNode('subgraph', subgraph)
|
||||
.addEdge(START, 'subgraph')
|
||||
// Additional parent graph setup would go here
|
||||
.compile();
|
||||
|
||||
// Example usage
|
||||
const initialState = { foo: "hello" };
|
||||
const initialState = { foo: 'hello' };
|
||||
const result = await parentGraph.invoke(initialState);
|
||||
console.log(`Result: ${JSON.stringify(result)}`); // Should append "bar" to the foo value
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { StateGraph, START, Annotation } from "@langchain/langgraph";
|
||||
import { StateGraph, START, Annotation } from '@langchain/langgraph';
|
||||
|
||||
const StateAnnotation = Annotation.Root({
|
||||
foo: Annotation(),
|
||||
@@ -12,11 +12,12 @@ const SubgraphStateAnnotation = Annotation.Root({
|
||||
|
||||
// Define subgraph
|
||||
const subgraphNode = async (state) => {
|
||||
return { bar: state.bar + "baz" };
|
||||
return { bar: state.bar + 'baz' };
|
||||
};
|
||||
|
||||
const subgraph = new StateGraph(SubgraphStateAnnotation)
|
||||
.addNode("subgraph", subgraphNode)
|
||||
.addNode('subgraph', subgraphNode)
|
||||
.addEdge(START, 'subgraph')
|
||||
// Additional subgraph setup would go here
|
||||
.compile();
|
||||
|
||||
@@ -33,13 +34,13 @@ const subgraphWrapperNode = async (state) => {
|
||||
};
|
||||
|
||||
const parentGraph = new StateGraph(StateAnnotation)
|
||||
.addNode("subgraph", subgraphWrapperNode)
|
||||
.addEdge(START, "subgraph")
|
||||
.addNode('subgraph', subgraphWrapperNode)
|
||||
.addEdge(START, 'subgraph')
|
||||
// Additional parent graph setup would go here
|
||||
.compile();
|
||||
|
||||
// Example usage
|
||||
|
||||
const initialState = { foo: "hello" };
|
||||
const initialState = { foo: 'hello' };
|
||||
const result = await parentGraph.invoke(initialState);
|
||||
console.log(`Result: ${JSON.stringify(result)}`); // Should transform foo->bar, append "baz", then transform bar->foo
|
||||
|
||||
@@ -78,4 +78,6 @@ initial_state = {
|
||||
|
||||
# Run the graph
|
||||
for output in graph.stream(initial_state):
|
||||
print("\nNew message:", output["messages"][-1].content[:100], "...")
|
||||
message_type = "generate" if "generate" in output else "reflect"
|
||||
print("\nNew message:", output[message_type]
|
||||
["messages"][-1].content[:100], "...")
|
||||
|
||||
@@ -19,6 +19,7 @@ def subgraph_node(state: SubgraphState):
|
||||
|
||||
subgraph_builder = StateGraph(SubgraphState)
|
||||
subgraph_builder.add_node("subgraph_node", subgraph_node)
|
||||
subgraph_builder.add_edge(START, "subgraph_node")
|
||||
# Additional subgraph setup would go here
|
||||
subgraph = subgraph_builder.compile()
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ class Joke(BaseModel):
|
||||
punchline: str = Field(description="The punchline to the joke")
|
||||
|
||||
|
||||
model = ChatOpenAI(model="gpt-3.5-turbo-0125", temperature=0)
|
||||
model = ChatOpenAI(model="gpt-4o", temperature=0)
|
||||
model = model.with_structured_output(Joke)
|
||||
|
||||
result = model.invoke("Tell me a joke about cats")
|
||||
|
||||
Reference in New Issue
Block a user