This project implements a Natural Language Understanding (NLU) flow using Firebase Genkit AI and Firebase Functions. The NLU flow detects intents and extracts entities from a given text input.
this project uses GitHub Models using the Genkit GitHub models plugin.
.firebaserc
.gitignore
firebase.json
function/
.eslintrc.js
.gitignore
nlu/
entities.yml
intents.yml
package.json
prompts/
nlu.prompt
src/
index.ts
tsconfig.dev.json
tsconfig.json
- Node.js v20
- Firebase CLI
- Genkit CLI
- TypeScript
- Github Account
- Clone the repository:
git clone https://github.com/xavidop/genkit-nlu.git cd genkit-nlu
-
Ensure you have the necessary Firebase configuration files (
firebase.json
,.firebaserc
). -
Update the
nlu/intents.yml
andnlu/entities.yml
files with your intents and entities.
Run ESLint to check for code quality issues:
npm run lint
Compile the TsypeScript code:
npm run build
Serve the functions locally:
npm run serve
Deploy the functions to Firebase:
npm run deploy
Run in the root directory:
GENKIT_ENV=dev firebase emulators:start --inspect-functions
Go to the function directory and run:
genkit start --attach http://localhost:3100 --port 4001
- Configuration: The
configureGenkit
function is called to set up the Genkit environment with plugins for Firebase, GitHub, and Dotprompt. It also sets the log level to "debug" and enables tracing and metrics.
configureGenkit({
plugins: [firebase(), github({}), dotprompt()],
logLevel: "debug",
enableTracingAndMetrics: true,
});
- Flow Definition: The nluFlow is defined using the onFlow function.
- Configuration: The flow is named
nluFlow
and has input and output schemas defined using zod. The input schema expects an object with a text string, and the output schema is a string. The flow does not require authentication (noAuth). - nluFlow: The flow processes the input:
- Schema Definition: Defines an
nluOutput
schema with intent and entities. - Prompt Reference: Gets a reference to the "nlu" dotprompt file.
- File Reading: Reads
intents.yml
andentities.yml
files. - Prompt Generation: Uses the
nluPrompt
to generate output based on the input text and the read intents and entities. - Return Output: Returns the generated output with type
nluOutput
.
- Schema Definition: Defines an
- Configuration: The flow is named
export const nluFlow = onFlow(
{
name: "nluFlow",
inputSchema: z.object({text: z.string()}),
outputSchema: z.string(),
authPolicy: noAuth(), // Not requiring authentication.
},
async (toDetect) => {
const nluOutput = defineSchema(
"nluOutput",
z.object({
intent: z.string(),
entities: z.map(z.string(), z.string()),
}),
);
const nluPrompt = promptRef("nlu");
const intents = readFileSync('nlu/intents.yml','utf8');
const entities = readFileSync('nlu/entities.yml','utf8');
const result = await nluPrompt.generate<typeof nluOutput>({
input: {
intents: intents,
entities: entities,
user_input: toDetect.text,
},
});
return result.output();
},
);
This nlu.prompt
file defines a prompt for a Natural Language Understanding (NLU) model. Here's a breakdown of its components:
-
Model Specification:
model: github/gpt-4o
This specifies the LLM model to be used, in this case,
github/gpt-4o
. -
Input Schema:
input: schema: intents: string entities: string user_input: string
This defines the input schema for the prompt. It expects three string inputs:
intents
: A string representing the intents.entities
: A string representing the entities.user_input
: A string representing the user's input text.
-
Output Specification:
output: format: json schema: nluOutput
This defines the output format and schema. The output will be in JSON format and should conform to the
nluOutput
schema. -
Prompt Text:
--- You are a NLU that detects intents and extract entities from a given text. you have these intents and utterances: {{intents}} You also have these entities: {{entities}} The user says: {{user_input}} Please specify the intent detected and the entity detected
This is the actual prompt text that will be used by the model. It provides context and instructions to the model:
- It describes the role of the model as an NLU system.
- It includes placeholders (
{{intents}}
,{{entities}}
,{{user_input}}
) that will be replaced with the actual input values. - It asks the model to specify the detected intent and entity based on the provided user input.
The main NLU flow is defined in index.ts. It reads intents and entities from YAML files and uses a prompt defined in nlu.prompt
to generate responses.
The intents are defined in the nlu/intents.yml
file. Each intent has a name and a list of training phrases.
As an example, the following intent is defined in the nlu/intents.yml
file:
order_shoes:
utterances:
- I want a pair of shoes from {shoes_brand}
- a shoes from {shoes_brand}
The format is as follows:
intent-name:
utterances:
- training phrase 1
- training phrase 2
- ...
The entities are defined in the nlu/entities.yml
file. Each entity has a name and a list of synonyms.
As an example, the following entity is defined in the nlu/entities.yml
file:
shoes_brand:
examples:
- Puma
- Nike
The format is as follows:
entity-name:
examples:
- synonym 1
- synonym 2
- ...
To trigger the NLU flow, send a request with the following structure:
{
"text": "Your input text here"
}
The response will be a JSON object with the following structure:
{
"intent": "intent-name",
"entities": {
"entity-name": "entity-value"
}
}
This project is licensed under the MIT License. See the LICENSE
file for details.
Contributions are welcome! Please open an issue or submit a pull request.
For any questions or issues, please open an issue in the repository.