-
Notifications
You must be signed in to change notification settings - Fork 2.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tool Support for Hedera Integration #7253
Open
aks-456
wants to merge
6
commits into
langchain-ai:main
Choose a base branch
from
aks-456:main
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
4c9e4f6
Added Hedera tool integration, and hedera doc
cde4312
added test cases
d0deaf2
updated package.json
36d3b7f
Fixed dependency
4d7d5ec
removed unnecessary line from example code
fbb1712
Moved hedera dependency into peer + dev
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
--- | ||
hide_table_of_contents: true | ||
--- | ||
|
||
import CodeBlock from "@theme/CodeBlock"; | ||
|
||
# Hedera Tool | ||
|
||
The Hedera Tool gives your agent the ability to create an account, delete an account, transfer | ||
between accounts, and query the balance of an account. | ||
|
||
## Setup | ||
|
||
To use the Hedera Tool you need to install the following official peer depencency: | ||
|
||
```bash npm2yarn | ||
npm install @hashgraph/sdk | ||
``` | ||
|
||
## Usage | ||
|
||
import ToolExample from "@examples/tools/hedera.ts"; | ||
|
||
<CodeBlock language="typescript">{ToolExample}</CodeBlock> | ||
|
||
## Related | ||
|
||
- Tool [conceptual guide](/docs/concepts/tools) | ||
- Tool [how-to guides](/docs/how_to/#tools) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import { | ||
HederaAccountBalance, | ||
HederaTransfer, | ||
HederaCreateAccount, | ||
HederaDeleteAccount, | ||
} from "@langchain/community/tools/hedera"; | ||
import { PrivateKey } from "@hashgraph/sdk" | ||
import { StructuredTool } from "@langchain/core/tools"; | ||
import { ChatOpenAI } from "@langchain/openai"; | ||
import type { ChatPromptTemplate } from "@langchain/core/prompts"; | ||
import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents"; | ||
import { pull } from "langchain/hub"; | ||
|
||
export async function run() { | ||
const llm = new ChatOpenAI({ | ||
model: "gpt-3.5-turbo", | ||
temperature: 0, | ||
}); | ||
|
||
// Initalize paramters for hedera tools to use | ||
const hederaParams = { | ||
credentials: { | ||
accountId: process.env.HEDERA_ACCOUNT_ID, | ||
privateKey: process.env.HEDERA_PRIVATE_KEY, | ||
}, | ||
network: "testnet", | ||
maxTransactionFee: 100, | ||
maxQueryPayment: 50, | ||
}; | ||
|
||
// Provide the hedera tools to be used | ||
const tools: StructuredTool[] = [ | ||
new HederaAccountBalance(hederaParams), | ||
new HederaTransfer(hederaParams), | ||
new HederaCreateAccount(hederaParams), | ||
new HederaDeleteAccount(hederaParams), | ||
]; | ||
|
||
// Setup the agent to use the hedera tool | ||
const prompt = await pull<ChatPromptTemplate>( | ||
"hwchase17/openai-functions-agent" | ||
); | ||
|
||
const agent = await createOpenAIFunctionsAgent({ | ||
llm, | ||
tools, | ||
prompt, | ||
}); | ||
|
||
const agentExecutor = new AgentExecutor({ | ||
agent, | ||
tools, | ||
verbose: false, | ||
}); | ||
|
||
const newAccountPrivateKey = PrivateKey.generateED25519(); | ||
const newAccountPublicKey = newAccountPrivateKey.publicKey; | ||
|
||
// Create hedera account | ||
const result1 = await agentExecutor.invoke({ | ||
input: `Can you create an account with public key ${newAccountPublicKey}`, | ||
}); | ||
console.log(result1.output); | ||
|
||
// Get the account balance of client operator | ||
const result2 = await agentExecutor.invoke({ | ||
input: `What is my account balance`, | ||
}); | ||
console.log(result2.output); | ||
|
||
// Get the account balance of a specific account | ||
const result3 = await agentExecutor.invoke({ | ||
input: `What is the account balance of 0.0.1111111`, | ||
}); | ||
console.log(result3.output); | ||
|
||
// Transfer tinybars between accounts | ||
const result4 = await agentExecutor.invoke({ | ||
input: `Can you transfer 100000000 tinybars from my account to 0.0.1111111`, | ||
}); | ||
console.log(result4.output); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import { Client, Hbar } from "@hashgraph/sdk"; | ||
import { z } from "zod"; | ||
import { StructuredTool } from "@langchain/core/tools"; | ||
import { getEnvironmentVariable } from "@langchain/core/utils/env"; | ||
|
||
export interface HederaBaseToolParams { | ||
credentials?: { | ||
accountId?: string; | ||
privateKey?: string; | ||
}; | ||
network?: string; | ||
maxTransactionFee?: number; | ||
maxQueryPayment?: number; | ||
} | ||
|
||
export abstract class HederaBaseTool extends StructuredTool { | ||
private CredentialsSchema = z | ||
.object({ | ||
accountId: z | ||
.string() | ||
.min(1) | ||
.default(getEnvironmentVariable("HEDERA_ACCOUNT_ID") ?? ""), | ||
privateKey: z | ||
.string() | ||
.min(1) | ||
.default(getEnvironmentVariable("HEDERA_PRIVATE_KEY") ?? ""), | ||
}) | ||
.refine( | ||
(credentials: { accountId: string; privateKey: string }) => | ||
credentials.accountId !== "" || credentials.privateKey !== "", | ||
{ | ||
message: | ||
"Missing HEDERA_ACCOUNT_ID or HEDERA_PRIVATE_KEY to interact with Hedera", | ||
} | ||
); | ||
|
||
private HederaBaseToolParamsSchema = z.object({ | ||
credentials: this.CredentialsSchema.default({}), | ||
network: z.enum(["mainnet", "testnet", "previewnet"]).default("testnet"), | ||
maxTransactionFee: z.number().default(100), | ||
maxQueryPayment: z.number().default(50), | ||
}); | ||
|
||
name = "Hedera Tool"; | ||
|
||
description = "A tool for interacting with the Hedera network."; | ||
|
||
protected client: Client; | ||
|
||
constructor(fields?: Partial<HederaBaseToolParams>) { | ||
super(...arguments); | ||
|
||
const { credentials, network, maxTransactionFee, maxQueryPayment } = | ||
this.HederaBaseToolParamsSchema.parse(fields); | ||
|
||
this.client = this.getHederaClient( | ||
network, | ||
credentials.accountId, | ||
credentials.privateKey, | ||
maxTransactionFee, | ||
maxQueryPayment | ||
); | ||
} | ||
|
||
private getHederaClient( | ||
network: "mainnet" | "testnet" | "previewnet", | ||
accountId: string, | ||
privateKey: string, | ||
maxTransactionFee: number, | ||
maxQueryPayment: number | ||
): Client { | ||
let client: Client; | ||
if (network === "mainnet") { | ||
client = Client.forMainnet(); | ||
} else if (network === "testnet") { | ||
client = Client.forTestnet(); | ||
} else { | ||
client = Client.forPreviewnet(); | ||
} | ||
client.setOperator(accountId, privateKey); | ||
client.setDefaultMaxTransactionFee(new Hbar(maxTransactionFee)); | ||
client.setDefaultMaxQueryPayment(new Hbar(maxQueryPayment)); | ||
return client; | ||
} | ||
} |
59 changes: 59 additions & 0 deletions
59
libs/langchain-community/src/tools/hedera/create_account.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { | ||
AccountCreateTransaction, | ||
AccountBalanceQuery, | ||
Hbar, | ||
PublicKey, | ||
} from "@hashgraph/sdk"; | ||
import { z } from "zod"; | ||
import { HederaBaseTool, HederaBaseToolParams } from "./base.js"; | ||
|
||
export class HederaCreateAccount extends HederaBaseTool { | ||
name = "hedera_create_account"; | ||
|
||
schema = z.object({ | ||
newAccountPublicKey: z.string(), | ||
initialAmount: z.number().default(1000), | ||
}); | ||
|
||
description = `A tool for creating a new Hedera account. Takes the new account's public key and the | ||
intial amount to set the starting balance of the account to. If no inital amount is provided | ||
it will set the starting balance to 1000 tinybar.`; | ||
|
||
constructor(fields?: HederaBaseToolParams) { | ||
super(fields); | ||
} | ||
|
||
async _call(arg: z.output<typeof this.schema>): Promise<string> { | ||
const { newAccountPublicKey, initialAmount } = arg; | ||
|
||
try { | ||
const publicKey = PublicKey.fromString(newAccountPublicKey); | ||
const newAccount = await new AccountCreateTransaction() | ||
.setKey(publicKey) | ||
.setInitialBalance(Hbar.fromTinybars(initialAmount)) | ||
.execute(this.client); | ||
|
||
const getReceipt = await newAccount.getReceipt(this.client); | ||
const newAccountId = getReceipt.accountId; | ||
|
||
if (!newAccountId) { | ||
throw new Error("Account creation failed."); | ||
} | ||
|
||
const accountBalance = await new AccountBalanceQuery() | ||
.setAccountId(newAccountId) | ||
.execute(this.client); | ||
|
||
return `Account created successfully. Account ID: ${newAccountId}, | ||
Initial Balance: ${accountBalance.hbars.toString()} tinybars`; | ||
} catch (error) { | ||
const typedError = error as Error; | ||
throw new Error(`Failed to create account: ${typedError.message}`); | ||
} | ||
} | ||
} | ||
|
||
export type AccountCreateSchema = { | ||
newAccountPublicKey: string; | ||
initialAmount?: number; | ||
}; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's use
createReactAgent
from@langchain/langgraph
here insteadThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jacoblee93 would it be possible to use
createStructuredChatAgent
instead?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, let's show the latest recommended practices