Skip to content

Commit

Permalink
(AI) AI Project Configuration OpenAI, Framework, LangChain LangSmith (#…
Browse files Browse the repository at this point in the history
…119)

* Add LangChain

* Add `intelligence` module

* Fix format

* Add LangChain Module

* Update .env

* Add intelligence feature controller

* Add controller for run feature API

* Add github issue intelligence

* Add langsmith tags for `runFeature`

* Fix lint
  • Loading branch information
devleejb authored Jan 30, 2024
1 parent f6bf00a commit 6e5f156
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 5 deletions.
6 changes: 6 additions & 0 deletions backend/src/intelligence/dto/run-feature.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { ApiProperty } from "@nestjs/swagger";

export class RunFeatureDto {
@ApiProperty({ type: String, description: "Content to run feature" })
content: string;
}
44 changes: 42 additions & 2 deletions backend/src/intelligence/intelligence.controller.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,44 @@
import { Controller } from "@nestjs/common";
import { Body, Controller, Param, Post, Req, Res } from "@nestjs/common";
import { ApiBearerAuth, ApiOkResponse, ApiOperation, ApiParam, ApiTags } from "@nestjs/swagger";
import { IntelligenceService } from "./intelligence.service";
import { AuthroizedRequest } from "src/utils/types/req.type";
import { Feature } from "./types/feature.type";
import { RunFeatureDto } from "./dto/run-feature.dto";
import { Response } from "express";

@ApiTags("Intelligences")
@ApiBearerAuth()
@Controller("intelligence")
export class IntelligenceController {}
export class IntelligenceController {
constructor(private intelligenceService: IntelligenceService) {}

@Post(":feature")
@ApiOperation({
summary: "Run the Yorkie Intelligence Feature",
description: "Run the selected yorkie intelligence",
})
@ApiParam({
name: "feature",
description: "Feature of intelligence to run",
enum: Feature,
})
@ApiOkResponse({ type: String })
async runFeature(
@Req() req: AuthroizedRequest,
@Res() res: Response,
@Param("feature") feature: Feature,
@Body() runFeatureDto: RunFeatureDto
): Promise<void> {
const stream = await this.intelligenceService.runFeature(
req.user.id,
feature,
runFeatureDto.content
);

for await (const chunk of stream) {
res.write(chunk);
}

res.end();
}
}
30 changes: 28 additions & 2 deletions backend/src/intelligence/intelligence.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,33 @@
import { Inject, Injectable } from "@nestjs/common";
import { Inject, Injectable, NotFoundException } from "@nestjs/common";
import { BaseChatModel } from "@langchain/core/language_models/chat_models";
import { Feature } from "./types/feature.type";
import { githubIssuePromptTemplate } from "./prompt/github-issue";
import { StringOutputParser } from "@langchain/core/output_parsers";

@Injectable()
export class IntelligenceService {
constructor(@Inject("BaseChatModel") private chatModel: BaseChatModel) {}
constructor(@Inject("ChatModel") private chatModel: BaseChatModel) {}

private selectPromptTemplate(feature: Feature) {
const promptTemplates = {
[Feature.GITHUB_ISSUE]: githubIssuePromptTemplate,
};
const selectedPrompt = promptTemplates[feature];

if (!selectedPrompt) throw new NotFoundException();

return selectedPrompt;
}

async runFeature(userId: string, feature: Feature, content: string) {
const promptTemplate = this.selectPromptTemplate(feature);
const prompt = await promptTemplate.format({
content,
});
const parser = new StringOutputParser();

return this.chatModel.pipe(parser).stream(prompt, {
tags: [feature, userId],
});
}
}
82 changes: 82 additions & 0 deletions backend/src/intelligence/prompt/github-issue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { ChatPromptTemplate, FewShotChatMessagePromptTemplate } from "langchain/prompts";

const examplePrompt = ChatPromptTemplate.fromTemplate(
"## Title\n{title}\n## Issue Type\n{issueType}\n## Content\n{content}"
);

const examples = [
{
title: "Error with `qemu` when launching `yorkie` project using `yorkieteam/yorkie` image on Apple M1",
issueType: "bug 🐞",
content: `<!-- Please use this template while reporting a bug and provide as much info as possible. Not doing so may result in your bug not being addressed in a timely manner. Thanks!
-->
**What happened**:
When launch \`yorkie\` project using \`yorkieteam/yorkie\` image. got error about \`qemu\` like below.
\`\`\`sh
yorkie | qemu: uncaught target signal 11 (Segmentation fault) - core dumped
\`\`\`
this is known issue on \`QEMU\` and I can not find how to resolve. but I attached related urls.
**What you expected to happen**:
\`yorkie\` work properly.
**How to reproduce it (as minimally and precisely as possible)**:
referenced [this issue](https://gitlab.com/qemu-project/qemu/-/issues/340) which gitlab, \`QEMU\`'s original repository.
**Rechardson Dx** said try to edit \`dockerfile\` and \`docker-compose\`. I do not tested.
**Anything else we need to know?**:
I attached related urls below
- [QEMU issue](https://gitlab.com/qemu-project/qemu/-/issues/340)
- [stackoverflow answer about qemu](https://stackoverflow.com/questions/68862313/qemu-uncaught-target-signal-11-segmentation-fault-core-dumped-in-docker-con)
**Environment**:
- Operating system: OSX Big Sur 11.5.2 apple m1
- Browser and version: chrome, safari
- Yorkie version (use \`yorkie version\`): 0.1.6
- Yorkie JS SDK version: 0.1.6
`,
},
{
title: "Introduce broadcast API for event sharing",
issueType: "enhancement 🌟",
content: `<!-- Please only use this template for submitting enhancement requests -->
**What would you like to be added**:
Yorkie presently relies on the Publish-Subscribe model for sharing document and presence events (refer to: [pub-sub.md](https://github.com/yorkie-team/yorkie/blob/main/design/pub-sub.md)).
However, this lacks the capability to extend its scope to encompass additional event types, notably notifications for end users concerning new document updates or comments.
To address this limitation, the introduction of a "broadcast" feature is recommended.
This feature would enable users to define and share a wider range of general events beyond the existing document and presence events.
It's also related to #442, which extracts \`Room\` from \`Document\` and moves \`Presence\` from \`Client\` to \`Room\`.
**Why is this needed**:
Provide a more comprehensive event-sharing mechanism that satisfies various use cases.`,
},
{
title: "Enhance Tree.Edit to manage Merge and Split scenarios",
issueType: "common issue 🐾",
content: `<!-- Please only use this template for submitting common issues -->
**Description**:
Move \`Client.Watch\` inside \`Client.Attach\` and hide it from the external interface.
Go SDK is just used in integration tests of servers without other SDK installations. So it was OK to expose \`Client.Watch\` to the external interface. But by adding more and more features to the SDK, it is quite difficult to keep simple tests.
Let's move Client.Watch inside Client.Attach and hide it from the external interface to maintain consistency with other SDKs and simplify testing.
**Why**:
Keep the product simple`,
},
];

export const githubIssuePromptTemplate = new FewShotChatMessagePromptTemplate({
prefix: `I want you to act as a GitHub Issue writer. I will provide brief information about the GitHub issue I want to create, and you should write the GitHub issue based on the examples I provide.
The types of issues you can write are bug 🐞 or enhancement 🌟. Please ensure that you follow the template used in each type of issue example provided. Please write your responses in English.`,
suffix: "Brief information about the GitHub issue: {content}",
examplePrompt,
examples,
inputVariables: ["content"],
});
4 changes: 4 additions & 0 deletions backend/src/intelligence/types/feature.type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export enum Feature {
GITHUB_ISSUE = "github-issue",
GITHUB_PR = "github-pr",
}
2 changes: 1 addition & 1 deletion backend/src/langchain/langchain.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ChatOpenAI } from "@langchain/openai";
import { BaseChatModel } from "@langchain/core/language_models/chat_models";

const chatModelFactory = {
provide: "BaseChatModel",
provide: "ChatModel",
useFactory: () => new ChatOpenAI({}) as BaseChatModel,
};

Expand Down

0 comments on commit 6e5f156

Please sign in to comment.