-
Notifications
You must be signed in to change notification settings - Fork 203
Create LEGALFLY Agent sample in TypeScript and Python #71
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
Changes from 8 commits
8d029d8
d224889
6ed0de0
89f8e81
30f8784
311ff3c
6cb74b9
68f3ec8
854f5a0
0de9f79
5a8707a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| PROJECT_CONNECTION_STRING= | ||
| MODEL_DEPLOYMENT_NAME= | ||
| LEGALFLY_API_CONNECTION_NAME= |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| bun.lock |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| # LEGALFLY | ||
|
|
||
| ## Description | ||
|
|
||
| Legal insights grounded in trusted sources from your jurisdiction. | ||
|
|
||
| ## Prerequisites | ||
|
|
||
|
||
| - Obtain an API key for your [LEGALFLY developer account](https://www.legalfly.com/ai-foundry-agents). | ||
|
||
|
|
||
| ## Setup | ||
|
|
||
| 1. Go to [Azure AI Foundry portal](https://ai.azure.com/) and select your AI Project. Select **Management Center**. | ||
| 2. Select **+new connection** in the settings page. | ||
| 3. Select **custom keys** in **other resource types**. | ||
| 4. Enter the following information to create a connection to store your LEGALFLY key: | ||
| - Set **Custom keys** to "key", with the value being your LEGALFLY API key. | ||
| - Make sure **is secret** is checked. | ||
| - Set the connection name to your connection name. You use this connection name in your sample code or Foundry Portal later. | ||
| - For the **Access** setting, you can choose either _this project only_ or _shared to all projects_. Just make sure in your code, the connection string of the project you entered has access to this connection. | ||
|
|
||
| ## Use LEGALFLY | ||
|
||
|
|
||
| 1. To use the LEGALFLY tool in Azure AI Foundry, in the **Create and debug** screen for your agent, scroll down the **Setup** pane on the right to **action**. Then select **Add**. | ||
| 2. Select **LEGALFLY** and follow the prompts to add the tool. | ||
| 3. Give a name for your LEGALFLY tool and provide an optional description. | ||
| 4. Select the custom key connection you just created. | ||
| 5. Finish and start chatting. | ||
|
|
||
| ## Customer Support Contact | ||
|
||
sandergo90 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| { | ||
| "name": "legalfly", | ||
| "version": "1.0.0", | ||
| "description": "LEGALFLY AI Foundry Agent", | ||
| "license": "MIT", | ||
| "author": "Sander Goossens", | ||
| "main": "src/index.js", | ||
| "scripts": { | ||
| "start": "bun run src/index.ts" | ||
| }, | ||
| "dependencies": { | ||
| "@azure/ai-projects": "1.0.0-beta.5", | ||
| "@azure/identity": "4.9.1", | ||
| "dotenv": "16.5.0" | ||
| }, | ||
| "devDependencies": { | ||
| "@types/node": "22.15.17", | ||
| "ts-node": "10.9.2", | ||
| "typescript": "5.8.3" | ||
| } | ||
| } |
sandergo90 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,139 @@ | ||
| import "dotenv/config"; | ||
| import { | ||
| AIProjectsClient, | ||
| DoneEvent, | ||
| ErrorEvent, | ||
| isOutputOfType, | ||
| MessageStreamEvent, | ||
| RunStreamEvent, | ||
| ToolUtility, | ||
| type MessageDeltaChunk, | ||
| type MessageDeltaTextContent, | ||
| type MessageTextContentOutput, | ||
| } from "@azure/ai-projects"; | ||
| import { DefaultAzureCredential } from "@azure/identity"; | ||
|
|
||
| const connectionString = process.env.PROJECT_CONNECTION_STRING; | ||
| const model = process.env.MODEL_DEPLOYMENT_NAME ?? "gpt-4o"; | ||
| const connectionName = process.env.LEGALFLY_API_CONNECTION_NAME; | ||
|
|
||
| if (!connectionString) { | ||
| throw new Error( | ||
| "Please set the PROJECT_CONNECTION_STRING environment variable." | ||
| ); | ||
| } | ||
|
|
||
| const client = AIProjectsClient.fromConnectionString( | ||
| connectionString, | ||
| new DefaultAzureCredential() | ||
| ); | ||
|
|
||
| async function fetchOpenApiSpec() { | ||
| const openApiSpecUrl = "https://public-api.legalfly.com/docs/json"; | ||
| const response = await fetch(openApiSpecUrl); | ||
| if (!response.ok) { | ||
| throw new Error(`Failed to fetch OpenAPI spec: ${response.statusText}`); | ||
| } | ||
| return response.json(); | ||
| } | ||
|
|
||
| async function main() { | ||
| if (!connectionName) { | ||
| throw new Error( | ||
| "Please set the LEGALFLY_API_CONNECTION_NAME environment variable." | ||
| ); | ||
| } | ||
|
|
||
| const connection = await client.connections.getConnectionWithSecrets( | ||
| connectionName | ||
| ); | ||
|
|
||
| console.log(`Created connection, connection ID: ${connection.id}`); | ||
|
|
||
| const openApiSpec = await fetchOpenApiSpec(); | ||
| const openApiTool = ToolUtility.createOpenApiTool({ | ||
| spec: openApiSpec, | ||
| name: "getLegalCounsel", | ||
| auth: { | ||
| type: "connection", | ||
| // @ts-ignore | ||
| security_scheme: { | ||
| connectionId: connection.id, | ||
| }, | ||
| }, | ||
| }); | ||
|
|
||
| const agent = await client.agents.createAgent(model, { | ||
| name: "my-agent", | ||
| instructions: | ||
| "You are a helpful AI legal assistant. Act like a friendly person who possesses a lot of legal knowledge.", | ||
| tools: [openApiTool.definition], | ||
| }); | ||
| console.log(`Created agent, agent ID: ${agent.id}`); | ||
|
|
||
| const thread = await client.agents.createThread(); | ||
| console.log(`Created thread, thread ID: ${thread.id}`); | ||
|
|
||
| const message = await client.agents.createMessage(thread.id, { | ||
| role: "user", | ||
| content: "What do I need to start a company in California?", | ||
| }); | ||
| console.log(`Created message, message ID: ${message.id}`); | ||
|
|
||
| const streamEventMessages = await client.agents | ||
| .createRun(thread.id, agent.id) | ||
| .stream(); | ||
|
|
||
| for await (const eventMessage of streamEventMessages) { | ||
| switch (eventMessage.event) { | ||
| case RunStreamEvent.ThreadRunCreated: | ||
| console.log(`Run created: ${eventMessage.data}`); | ||
| break; | ||
| case MessageStreamEvent.ThreadMessageDelta: | ||
| { | ||
| const messageDelta = eventMessage.data as MessageDeltaChunk; | ||
| messageDelta.delta.content.forEach((contentPart) => { | ||
| if (contentPart.type === "text") { | ||
| const textContent = contentPart as MessageDeltaTextContent; | ||
| const textValue = textContent.text?.value || "No text"; | ||
| console.log(`Text: ${textValue}`); | ||
| } | ||
| }); | ||
| } | ||
| break; | ||
|
|
||
| case RunStreamEvent.ThreadRunCompleted: | ||
| console.log(`Run completed: ${eventMessage.data}`); | ||
| break; | ||
| case ErrorEvent.Error: | ||
| console.log(`An error occurred. Data ${eventMessage.data}`); | ||
| break; | ||
| case DoneEvent.Done: | ||
| console.log(`Done: ${eventMessage.data}`); | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| // 6. Print the messages from the agent | ||
| const messages = await client.agents.listMessages(thread.id); | ||
|
|
||
| // Messages iterate from oldest to newest | ||
| // messages[0] is the most recent | ||
| const messagesArray = messages.data; | ||
| for (let i = messagesArray.length - 1; i >= 0; i--) { | ||
| const m = messagesArray[i]; | ||
| console.log(`Type: ${m.content[0].type}`); | ||
| if (isOutputOfType<MessageTextContentOutput>(m.content[0], "text")) { | ||
| const textContent = m.content[0] as MessageTextContentOutput; | ||
| console.log(`Text: ${textContent.text.value}`); | ||
| } | ||
| } | ||
|
|
||
| // 7. Delete the agent once done | ||
| await client.agents.deleteAgent(agent.id); | ||
| } | ||
|
|
||
| main().catch((err) => { | ||
| console.error("The sample encountered an error:", err); | ||
| process.exit(1); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| { | ||
| "$schema": "https://json.schemastore.org/tsconfig", | ||
| "compilerOptions": { | ||
| "allowImportingTsExtensions": false, | ||
| "composite": true, | ||
| "declaration": true, | ||
| "declarationMap": true, | ||
| "emitDeclarationOnly": true, | ||
| "allowJs": true, | ||
| "incremental": true, | ||
| "allowSyntheticDefaultImports": true, | ||
| "esModuleInterop": true, | ||
| "forceConsistentCasingInFileNames": true, | ||
| "isolatedModules": true, | ||
| "module": "ESNext", | ||
| "moduleResolution": "Bundler", | ||
| "noFallthroughCasesInSwitch": true, | ||
| "noImplicitReturns": true, | ||
| "noUnusedLocals": true, | ||
| "noUnusedParameters": true, | ||
| "pretty": true, | ||
| "resolveJsonModule": true, | ||
| "skipLibCheck": true, | ||
| "strict": true, | ||
| "strictPropertyInitialization": false, | ||
| "useUnknownInCatchVariables": false | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| PROJECT_CONNECTION_STRING= | ||
| MODEL_DEPLOYMENT_NAME= | ||
| LEGALFLY_API_CONNECTION_NAME= |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| # LEGALFLY | ||
|
|
||
| ## Description | ||
|
|
||
| Legal insights grounded in trusted sources from your jurisdiction. | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| [Obtain an API key](https://www.legalfly.com/ai-foundry-agents) by filling in the request form. You'll receive the API key by e-mail within 1-2 working days. | ||
|
|
||
| ## Setup | ||
|
|
||
| 1. Go to [Azure AI Foundry portal](https://ai.azure.com/) and select your AI Project. Select **Management Center**. | ||
|
|
||
| 1. Select **+new connection** in the settings page. | ||
| 1. Select **custom keys** in **other resource types**. | ||
|
|
||
| 1. Enter the following information to create a connection to store your LEGALFLY key: | ||
| 1. Set **Custom keys** to "key", with the value being your LEGALFLY API key. | ||
| 1. Make sure **is secret** is checked. | ||
| 1. Set the connection name to your connection name. You use this connection name in your sample code or Foundry Portal later. | ||
| 1. For the **Access** setting, you can choose either _this project only_ or _shared to all projects_. Just make sure in your code, the connection string of the project you entered has access to this connection. | ||
|
|
||
| ## Use LEGALFLY through a code-first experience | ||
|
|
||
| 1. You can follow the [code sample](./main.py) to use LEGALFLY through Agent SDK. | ||
| 1. Before running the sample: | ||
| 1. pip install azure-ai-projects azure-ai-agents azure-identity python-dotenv | ||
| 1. Set these environment variables with your own values: | ||
| 1. PROJECT_CONNECTION_STRING - the Azure AI Agents connection string. | ||
|
||
| 1. MODEL_DEPLOYMENT_NAME - The deployment name of the AI model, as found under the "Name" column in the "Models + endpoints" tab in your Azure AI Foundry project. | ||
| 1. LEGALFLY_API_CONNECTION_NAME - The name of the connection for the LegalFly API. | ||
|
|
||
| ## Customer Support Contact | ||
|
|
||
| [email protected] | ||
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.
i dont think this file is needed?
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.
It is because this samples use bun instead of node so don't want to add it to the global .gitignore file.