-
Notifications
You must be signed in to change notification settings - Fork 0
/
openai-chat-with-tools.service.ts
73 lines (63 loc) · 2.7 KB
/
openai-chat-with-tools.service.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import { ChatPromptTemplate, MessagesPlaceholder } from "@langchain/core/prompts";
import { DynamicStructuredTool } from "@langchain/core/tools";
import { ChatOpenAI } from "@langchain/openai";
import { HttpService } from "@nestjs/axios";
import { Injectable } from "@nestjs/common";
import { AgentExecutor, createOpenAIFunctionsAgent } from "langchain/agents";
import { z } from "zod";
@Injectable()
export class OpenAIChatWithToolsService {
constructor(
private readonly openAI: ChatOpenAI,
private readonly httpService: HttpService,
) {}
async chatWithTools(address: string): Promise<string> {
const agent = await createOpenAIFunctionsAgent({
llm: this.openAI,
tools: [this.zipCodeTool],
prompt: this.prompt,
});
const agentExecutor = new AgentExecutor({ agent, tools: [this.zipCodeTool], verbose: true });
return (await agentExecutor.invoke({ inputAddress: address })).output as string;
}
private prompt = ChatPromptTemplate.fromMessages([
[
"system",
`The by the user provided text contains a possibly incorrectly formatted address.
It should include a streetAddress, houseNumber, city and a zipCode.
Return the address in the format: streetAddress houseNumber, zipCode city.
If the zipCode is missing, retrieve it and add it to the result.
If any other field is missing, omit it in the response.
Return only the formatted address no additional explanation or text.
EXAMPLES:
- "Riesstraße 22 München" -> "Riesstraße 22, 80992 München"
- "Oder Strasse 22 81669 München" -> "Oder Strasse 22, 81669 München"
`,
],
["user", "{inputAddress}"],
// this placeholder is needed for the agent to store intermediate information over multiple requests to OpenAI
new MessagesPlaceholder("agent_scratchpad"),
]);
private zipCodeTool = new DynamicStructuredTool({
name: "get-zip-code",
description: "Retrieve the zip code for the city and street name",
schema: z.object({
city: z.string().describe("The city name."),
streetName: z.string().describe(`
The name of the street.
It is important that street names which include the word "Straße" or "Strasse"
case insensitive are replaced it with "Str." or "str.".
examples:
- "Riesstraße" -> "Riesstr."
- "Oder Strasse" -> "Oder Str."
- "Nelkenweg" -> "Nelkenweg"
`),
}),
func: async ({ city, streetName }) => {
const response = await this.httpService.axiosRef.get(
`https://openplzapi.org/de/Streets?name=${streetName}&locality=${city}`,
);
return response.data.find((entry) => entry.name === streetName)?.postalCode;
},
});
}