annotation-replacer.ts 1.6 KB

1234567891011121314151617181920212223242526272829303132333435
  1. // See: https://platform.openai.com/docs/assistants/tools/file-search#step-5-create-a-run-and-check-the-output
  2. import type { IPageHasId } from '@growi/core/dist/interfaces';
  3. import type { MessageDelta } from 'openai/resources/beta/threads/messages.mjs';
  4. import VectorStoreFileRelationModel, { type VectorStoreFileRelation } from '~/features/openai/server/models/vector-store-file-relation';
  5. import { configManager } from '~/server/service/config-manager';
  6. import { getTranslation } from '~/server/service/i18next';
  7. type PopulatedVectorStoreFileRelation = Omit<VectorStoreFileRelation, 'pageId'> & { pageId: IPageHasId }
  8. export const annotationReplacer = async(delta: MessageDelta): Promise<void> => {
  9. const content = delta.content?.[0];
  10. if (content?.type === 'text' && content?.text?.annotations != null) {
  11. const annotations = content?.text?.annotations;
  12. for await (const annotation of annotations) {
  13. if (annotation.type === 'file_citation' && annotation.text != null) {
  14. const vectorStoreFileRelation = await VectorStoreFileRelationModel
  15. .findOne({ fileIds: { $in: [annotation.file_citation?.file_id] } })
  16. .populate('pageId', 'path') as PopulatedVectorStoreFileRelation;
  17. if (vectorStoreFileRelation != null) {
  18. const { t } = await getTranslation();
  19. const appSiteUrl = configManager?.getConfig('crowi', 'app:siteUrl');
  20. content.text.value = content.text.value?.replace(
  21. annotation.text,
  22. ` [${t('source')}: [${vectorStoreFileRelation.pageId.path}](${appSiteUrl}/${vectorStoreFileRelation.pageId._id})]`,
  23. );
  24. }
  25. }
  26. }
  27. }
  28. };