Skip to content
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

V3.0.5 #14

Merged
merged 30 commits into from
Dec 23, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
5860a5b
feat: interrupted tool call
meta-d Dec 11, 2024
965dfc9
feat: sensitive tools
meta-d Dec 11, 2024
35d4ea0
feat: Interrupted chat
meta-d Dec 12, 2024
c227eba
feat: human in the loop
meta-d Dec 12, 2024
bedd050
feat: reject INTERRUPTED chat
meta-d Dec 12, 2024
b3ee9c0
feat: mutiple tool calls info
meta-d Dec 12, 2024
0e12a68
feat: sensitive operation tool call
meta-d Dec 13, 2024
44f2c35
Merge branch 'develop' into v3.0.4
meta-d Dec 13, 2024
82aaa73
version 3.0.4
meta-d Dec 13, 2024
6a37d8b
feat: primary agent not sensitive
meta-d Dec 13, 2024
d1c7743
feat: conversation summarize
meta-d Dec 14, 2024
7f3e7c7
feat: long term memory
meta-d Dec 15, 2024
4eb5b4b
feat: feeback to summarize long-term memory
meta-d Dec 16, 2024
2bd4bc2
feat: fix agent primary
meta-d Dec 16, 2024
37eef2c
feat: xpert's memory page
meta-d Dec 17, 2024
8d7d0ff
feat: long term memory of xpert
meta-d Dec 17, 2024
2aa1b8a
feat: use long-term memory in chat
meta-d Dec 18, 2024
ff0cc77
feat: add findMyAll in curd service
meta-d Dec 18, 2024
6ab7736
feat: register user
meta-d Dec 18, 2024
b33162c
feat: long-term memory every user
meta-d Dec 18, 2024
2a97e95
feat: long-term memory
meta-d Dec 18, 2024
49b660e
feat: execution tools events
meta-d Dec 18, 2024
73561a6
feat: fix xpert memory
meta-d Dec 18, 2024
3431705
feat: semantic search for long-term store
meta-d Dec 19, 2024
8dd154f
feat: long-term trigger events
meta-d Dec 19, 2024
803fc7a
feat: memory profile
meta-d Dec 20, 2024
7756017
version 3.0.5
meta-d Dec 20, 2024
867226a
feat: update mysql client to 2
meta-d Dec 20, 2024
c90a8ff
feat: memory of xpert
meta-d Dec 20, 2024
6c0cc56
fix: null memory store
meta-d Dec 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat: memory profile
  • Loading branch information
meta-d committed Dec 20, 2024
commit 803fc7a9475ff073c9c6ac5e7511dbcfd959edbb
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,11 @@
<div class="flex justify-between items-center h-11 pl-3 pr-6">
<div class="flex items-center space-x-1">
<div class="h2 text-sm">{{'PAC.Copilot.Prompt' | translate: {Default: 'Prompt'} }}</div>
<div class="p-[1px] w-4 h-4 shrink-0 text-text-quaternary hover:text-text-tertiary"
<div class="p-[1px] w-4 h-4 flex items-center shrink-0 text-text-quaternary hover:text-text-tertiary"
[matTooltip]="tooltip()"
matTooltipPosition="above"
>
<svg
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
fill="currentColor"
class="w-full h-full"
>
<path
d="M12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22ZM12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20ZM11 15H13V17H11V15ZM13 13.3551V14H11V12.5C11 11.9477 11.4477 11.5 12 11.5C12.8284 11.5 13.5 10.8284 13.5 10C13.5 9.17157 12.8284 8.5 12 8.5C11.2723 8.5 10.6656 9.01823 10.5288 9.70577L8.56731 9.31346C8.88637 7.70919 10.302 6.5 12 6.5C13.933 6.5 15.5 8.067 15.5 10C15.5 11.5855 14.4457 12.9248 13 13.3551Z"
></path>
</svg>
<i class="ri-question-line"></i>
</div>
</div>
<div class="flex items-center">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { CdkMenuModule } from '@angular/cdk/menu'
import { CommonModule } from '@angular/common'
import { ChangeDetectionStrategy, Component, computed, ElementRef, HostListener, inject, input, model, viewChild } from '@angular/core'
import { ChangeDetectionStrategy, Component, computed, effect, ElementRef, HostListener, inject, input, model, numberAttribute, viewChild } from '@angular/core'
import { FormsModule } from '@angular/forms'
import { MatDialog } from '@angular/material/dialog'
import { MatTooltipModule } from '@angular/material/tooltip'
Expand All @@ -22,18 +22,28 @@ export class CopilotPromptEditorComponent {

readonly regex = `{{(.*?)}}`

readonly initHeight = input<number>(210)
readonly initHeight = input<number, number | string>(210, {
transform: numberAttribute
})
readonly tooltip = input<string>()

readonly prompt = model<string>()
readonly promptLength = computed(() => this.prompt()?.length)


height = this.initHeight(); // 初始高度
height = this.initHeight();
private isResizing = false;
private startY = 0;
private startHeight = 0;

constructor() {
effect(() => {
if (this.initHeight()) {
this.height = this.initHeight()
}
})
}

generate() {
this.#dialog.open(CopilotPromptGeneratorComponent, {
panelClass: 'large'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@
</div>

@if (profileEnabled) {
<copilot-prompt-editor @heightChangeAnimation class="relative shadow-md ngm-card-border-gradient self-stretch"
[tooltip]="'PAC.Xpert.SystemPromptTooltip' | translate: {Default: 'Prompts guide AI reponses with instructions and contraints. Insert parameters like {{input}}. This prompt won\'t be visible to users.'}"
<copilot-prompt-editor @heightChangeAnimation class="relative ngm-card-border-gradient self-stretch"
[tooltip]="'PAC.Xpert.ProfileMemoryPromptTooltip' | translate: {Default: 'Prompt guide AI to extract user information through instructions and constraints'}"
[(prompt)]="profilePrompt"
initHeight="100"
/>
}

Expand All @@ -35,10 +36,23 @@
</mat-checkbox>

@if (qaEnabled) {
<copilot-prompt-editor @heightChangeAnimation class="relative shadow-md ngm-card-border-gradient self-stretch"
[tooltip]="'PAC.Xpert.SystemPromptTooltip' | translate: {Default: 'Prompts guide AI reponses with instructions and contraints. Insert parameters like {{input}}. This prompt won\'t be visible to users.'}"
<copilot-prompt-editor @heightChangeAnimation class="relative shadow-sm ngm-card-border-gradient self-stretch"
[tooltip]="'PAC.Xpert.QAMemoryPromptTooltip' | translate: {Default: 'Prompt to use instructions and constraints to guide AI to summarize successful experiences of conversation question and answer'}"
[(prompt)]="qaPrompt"
initHeight="100"
/>
}

</section>
</section>

<section class="memory-section"
[ngmTooltip]="customInDevelopment"
[hideDelay]="100">
<mat-checkbox class="memory-checkbox" >
{{ 'PAC.Xpert.LongTermMemoryTypeEnum.Custom' | translate: {Default: 'Custom'} }}
</mat-checkbox>
</section>

<ng-template #customInDevelopment >
<pac-in-development @overlayAnimation1 feature="Custom Memory" class="w-80" />
</ng-template>
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import { FormsModule } from '@angular/forms'
import { MatSliderModule } from '@angular/material/slider'
import { MatTooltipModule } from '@angular/material/tooltip'
import { LongTermMemoryTypeEnum, TLongTermMemory, TLongTermMemoryConfig } from '@metad/contracts'
import { IfAnimations } from '@metad/core'
import { IfAnimations, OverlayAnimations } from '@metad/core'
import { NgmRadioSelectComponent } from '@metad/ocap-angular/common'
import { TranslateModule } from '@ngx-translate/core'
import { CopilotPromptEditorComponent } from '../../../../../@shared/copilot'
import { XpertStudioApiService } from '../../domain'
import { injectTranslate } from 'apps/cloud/src/app/@core'
import { MatCheckboxModule } from '@angular/material/checkbox'
import { InDevelopmentComponent } from 'apps/cloud/src/app/@theme'
import { NgmTooltipDirective } from '@metad/ocap-angular/core'

@Component({
selector: 'xpert-studio-features-memory',
Expand All @@ -26,11 +28,13 @@ import { MatCheckboxModule } from '@angular/material/checkbox'
MatCheckboxModule,
NgmRadioSelectComponent,

CopilotPromptEditorComponent
NgmTooltipDirective,
CopilotPromptEditorComponent,
InDevelopmentComponent
],
templateUrl: './memory.component.html',
styleUrl: './memory.component.scss',
animations: [...IfAnimations]
animations: [...IfAnimations, ...OverlayAnimations]
})
export class XpertStudioFeaturesMemoryComponent {
eLongTermMemoryTypeEnum = LongTermMemoryTypeEnum
Expand Down
7 changes: 5 additions & 2 deletions apps/cloud/src/assets/i18n/zh-Hans.json
Original file line number Diff line number Diff line change
Expand Up @@ -2062,9 +2062,12 @@
"LongTermMemoryTypeEnum": {
"UserProfile": "用户个人资料",
"Profile": "用户配置",
"QuestionAnswer": "问题/回答"
"QuestionAnswer": "问题/回答",
"Custom": "自定义"
},
"AfterSecondsTooltip": "会话结束多少秒后如果没有继续对话则进行总结"
"AfterSecondsTooltip": "会话结束多少秒后如果没有继续对话则进行总结",
"ProfileMemoryPromptTooltip": "提示用于通过指令和约束引导 AI 提取用户信息",
"QAMemoryPromptTooltip": "提示用于通过指令和约束引导 AI 总结对话问题和答案的成功经验"
},
"title": {
"short": "Xpert AI"
Expand Down
2 changes: 1 addition & 1 deletion packages/contracts/src/ai/xpert.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ export type TLongTermMemoryConfig = {
*/
export type TLongTermMemory = {
enabled?: boolean
type?: LongTermMemoryTypeEnum
// type?: LongTermMemoryTypeEnum
copilotModel?: TCopilotModel
profile?: TLongTermMemoryConfig & {
afterSeconds?: number
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ export class ScheduleSummaryJobHandler implements ICommandHandler<ScheduleSummar
} catch (error) {
this.logger.error(`Failed to add summarize job for conversation ${conversationId}:`, error)
}
}, memory.profile?.afterSeconds ?? 10000) // 10 秒延迟
}, memory.profile?.afterSeconds ? (memory.profile.afterSeconds * 1000) : 10000) // x 秒延迟

this.schedulerRegistry.addTimeout(conversationId, timeout)
this.logger.debug(`Scheduled summary job for conversation ${conversationId} in 5 seconds.`)
this.logger.debug(`Scheduled summary job for conversation ${conversationId} in ${memory.profile?.afterSeconds ?? 10} seconds.`)
}
}
12 changes: 8 additions & 4 deletions packages/server-ai/src/copilot-store/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ export class CopilotMemoryStore extends BaseStore {
await this.pgPool.query(query, param)
}
} else {
console.log(query, params)
await this.pgPool.query(query, params)
}
}
Expand Down Expand Up @@ -240,15 +241,18 @@ export class CopilotMemoryStore extends BaseStore {
let embeddingRequest: [string, Array<[string, string, string, string]>] | null = null
if (inserts.length > 0) {
const values: string[] = []
// const insertionParams: any[] = [];
const insertionParams: any[] = [];
const vectorValues: string[] = []
const embeddingRequestParams: Array<[string, string, string, string]> = []

// First handle main store insertions
let index = 1;
for (const op of inserts) {
values.push(
`('${this.options?.tenantId}', '${this.options?.organizationId}', '${this.options?.userId}', '${op.namespace.join(':')}', '${op.key}', '${JSON.stringify(op.value)}', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)`
`('${this.options?.tenantId}', '${this.options?.organizationId}', '${this.options?.userId}', '${op.namespace.join(':')}', '${op.key}', $${index}, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)`
)
index++
insertionParams.push(JSON.stringify(op.value))
}

// Then handle embeddings if configured
Expand Down Expand Up @@ -284,7 +288,7 @@ export class CopilotMemoryStore extends BaseStore {
SET value = EXCLUDED.value,
"updatedAt" = CURRENT_TIMESTAMP
`
queries.push([query, null])
queries.push([query, insertionParams])

if (vectorValues.length > 0) {
const vectorValuesStr = vectorValues.join(',')
Expand Down Expand Up @@ -536,7 +540,7 @@ function namespaceToText(namespace: string[], handleWildcards = false): string {
if (handleWildcards) {
namespace = namespace.map((val) => (val === '*' ? '%' : val))
}
return namespace.join('.')
return namespace.join(':')
}

function groupOps(ops: Iterable<Operation>): [Record<string, Array<[number, Operation]>>, number] {
Expand Down
17 changes: 17 additions & 0 deletions packages/server-ai/src/copilot-store/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { SearchItem } from "@langchain/langgraph-checkpoint";

/**
* Tokenize a JSON path into parts.
* @example
Expand Down Expand Up @@ -309,4 +311,19 @@ export function decodeNsBytes(namespace: string | Uint8Array | any[]): string[]
namespace = new TextDecoder().decode(namespace).slice(1);
}
return namespace.split(":");
}

export function memoryPrompt(memory: SearchItem[],) {
return memory.map((item) => {
if (item.value.profile) {
return `<profile>\n${item.value.profile}\n</profile>`
} else if (item.value.output) {
return `<example>
<input>${item.value.input}</input>
<output>${item.value.output}</output>
</example>`
} else {
return ''
}
}).join('\n')
}
8 changes: 5 additions & 3 deletions packages/server-ai/src/xpert-agent/commands/chat.command.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ToolCall } from '@langchain/core/dist/messages/tool'
import { IXpert, IXpertAgentExecution, TChatOptions } from '@metad/contracts'
import { SearchItem } from '@langchain/langgraph-checkpoint'
import { IXpert, IXpertAgentExecution, TChatOptions, ToolCall } from '@metad/contracts'
import { ICommand } from '@nestjs/cqrs'

/**
Expand All @@ -14,7 +14,7 @@ export class XpertAgentChatCommand implements ICommand {
[key: string]: unknown
},
public readonly agentKey: string,
public readonly xpert: Partial<IXpert>,
public readonly xpert: IXpert,
public readonly options: TChatOptions & {
// Use xpert's draft
isDraft?: boolean
Expand All @@ -25,6 +25,8 @@ export class XpertAgentChatCommand implements ICommand {

toolCalls?: ToolCall[]
reject?: boolean

memories?: SearchItem[]
}
) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export class XpertAgentExecuteCommand implements ICommand {
/**
* Memory
*/
memory?: SearchItem[]
memories?: SearchItem[]
}
) {}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,20 @@
import { MessageContent } from '@langchain/core/messages'
import { BaseStore, NodeInterrupt } from '@langchain/langgraph'
import { NodeInterrupt } from '@langchain/langgraph'
import {
ChatMessageEventTypeEnum,
ChatMessageTypeEnum,
IXpert,
LongTermMemoryTypeEnum,
TSensitiveOperation,
XpertAgentExecutionStatusEnum
} from '@metad/contracts'
import { getErrorMessage } from '@metad/server-common'
import { RequestContext } from '@metad/server-core'
import { Logger } from '@nestjs/common'
import { CommandBus, CommandHandler, ICommandHandler, QueryBus } from '@nestjs/cqrs'
import { catchError, concat, EMPTY, from, map, Observable, of, Subject, switchMap, takeUntil, tap } from 'rxjs'
import { XpertAgentExecutionUpsertCommand } from '../../../xpert-agent-execution/commands'
import { XpertAgentExecutionOneQuery } from '../../../xpert-agent-execution/queries'
import { XpertAgentChatCommand } from '../chat.command'
import { XpertAgentExecuteCommand } from '../execute.command'
import { GetXpertMemoryEmbeddingsQuery } from '../../../xpert/queries'
import { CreateCopilotStoreCommand } from '../../../copilot-store'

@CommandHandler(XpertAgentChatCommand)
export class XpertAgentChatHandler implements ICommandHandler<XpertAgentChatCommand> {
Expand All @@ -31,7 +27,8 @@ export class XpertAgentChatHandler implements ICommandHandler<XpertAgentChatComm

public async execute(command: XpertAgentChatCommand): Promise<Observable<MessageEvent>> {
const { input, xpert, agentKey, options } = command
let { execution } = options
// eslint-disable-next-line @typescript-eslint/no-unused-vars, prefer-const
let { execution, memories } = options
execution = await this.commandBus.execute(
new XpertAgentExecutionUpsertCommand({
id: execution?.id,
Expand All @@ -45,9 +42,6 @@ export class XpertAgentChatHandler implements ICommandHandler<XpertAgentChatComm

const timeStart = Date.now()

// Long-term memory
const memory = await this.getLongTermMemory(options.isDraft ? xpert.draft?.team : xpert, RequestContext.currentUserId())

const thread_id = execution.threadId
let operation: TSensitiveOperation = null
return new Observable<MessageEvent>((subscriber) => {
Expand Down Expand Up @@ -75,7 +69,7 @@ export class XpertAgentChatHandler implements ICommandHandler<XpertAgentChatComm
thread_id,
execution,
subscriber,
memory
memories
})
)
).pipe(
Expand Down Expand Up @@ -168,36 +162,4 @@ export class XpertAgentChatHandler implements ICommandHandler<XpertAgentChatComm
})
)
}

async getLongTermMemory(xpert: Partial<IXpert>, userId: string) {
const { tenantId, organizationId } = xpert
const memory = xpert.memory
if (!memory?.enabled) {
return null
}

const fields = []
if (memory.type === LongTermMemoryTypeEnum.QA) {
fields.push('input')
} else {
fields.push('profile')
}

const embeddings = await this.queryBus.execute(new GetXpertMemoryEmbeddingsQuery(tenantId, organizationId, memory, {} ))

const store = await this.commandBus.execute<CreateCopilotStoreCommand, BaseStore>(
new CreateCopilotStoreCommand({
tenantId,
organizationId,
userId,
index: {
dims: null,
embeddings,
fields
}
})
)

return await store.search([xpert.id,])
}
}
Loading