Skip to content

Commit

Permalink
Bugfixes for PlantUMLTransformer
Browse files Browse the repository at this point in the history
  • Loading branch information
jschm42 committed Apr 11, 2024
1 parent dbd9fa8 commit 1d83692
Show file tree
Hide file tree
Showing 10 changed files with 73 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import reactor.core.publisher.Flux;
Expand Down Expand Up @@ -229,20 +228,17 @@ public ResponseEntity<byte[]> getImage(@PathVariable String threadId,
}

@DeleteMapping("/threads/{threadId}")
@ResponseBody
public void deleteThread(@PathVariable("threadId") String threadId) {
assistantService.deleteThread(threadId);
}

@PostMapping("/threads/{threadId}/title")
@ResponseBody
public ThreadTitleDto updateThreadTitle(@PathVariable("threadId") String threadId,
@RequestBody ThreadTitleUpdateRequestDto request) {
return assistantService.updateThreadTitle(threadId, request);
}

@PostMapping("/threads/{threadId}/title/generate")
@ResponseBody
public ThreadTitleDto generateThreadTitle(@PathVariable("threadId") String threadId,
@RequestBody ThreadTitleGenerationRequestDto request) {
return assistantService.generateThreadTitle(threadId, request);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public MessageProcessor(FileStorageService fileStorageService,
transformers.add(new CodeBlockTransformer());
transformers.add(new CodePhraseTransformer());
transformers.add(new MarkdownHeaderTransformer());
transformers.add(new MarkdownListTransformer());
// transformers.add(new MarkdownListTransformer());
transformers.add(new MarkdownTextTransformer());
transformers.add(new NewLineTransformer());

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023 Jean Schmitz.
* Copyright (c) 2023-2024 Jean Schmitz.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -18,73 +18,78 @@

import com.talkforgeai.backend.transformers.dto.TransformerContext;
import com.talkforgeai.service.plantuml.PlantUMLService;
import net.sourceforge.plantuml.core.DiagramDescription;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.sourceforge.plantuml.core.DiagramDescription;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class PlantUMLTransformer implements Transformer {
private static final Logger LOGGER = LoggerFactory.getLogger(PlantUMLTransformer.class);
private static final Pattern UrlRegEx = Pattern.compile("```(.*)\n@startuml\n([\\s\\S]*?)```", Pattern.MULTILINE);
final String template = """
%s
<div class="card shadow">
<div class="card-body">
<img src='%s' title='%s'>
</div>
</div>
%s
""";
private final PlantUMLService service;

public PlantUMLTransformer(PlantUMLService service) {
this.service = service;
}

@Override
public String process(String content, TransformerContext context) {
Matcher matcher = UrlRegEx.matcher(content);
static final String IMAGE_URL = "/api/v1/threads/%s/%s";

while (matcher.find()) {
String fullTag = matcher.group(0);
String lang = matcher.group(1);
String code = "@startuml\n" + matcher.group(2);
static final String TEMPLATE = """
%s
<div class="card shadow">
<div class="card-body">
<img src='%s' title='%s'>
</div>
</div>
%s
""";
private static final Logger LOGGER = LoggerFactory.getLogger(PlantUMLTransformer.class);
private static final Pattern UrlRegEx = Pattern.compile("```(.*)\n@startuml\n([\\s\\S]*?)```",
Pattern.MULTILINE);
private final PlantUMLService service;

String fileName = UUID.randomUUID() + "_plantuml.png";
Path subDirectoryPath = context.threadDirectory().resolve(context.messageId());
Path localFilePath = subDirectoryPath.resolve(fileName);
public PlantUMLTransformer(PlantUMLService service) {
this.service = service;
}

// Ensure the directory exists and is writable
try {
if (!Files.exists(subDirectoryPath)) {
Files.createDirectories(subDirectoryPath);
}
if (!Files.isWritable(subDirectoryPath)) {
throw new IOException("Directory is not writable: " + subDirectoryPath);
}
} catch (IOException ioEx) {
throw new RuntimeException(ioEx);
}
@Override
public String process(String content, TransformerContext context) {
Matcher matcher = UrlRegEx.matcher(content);

DiagramDescription diagramDescription = service.generateUmlDiagram(code, localFilePath.toString());
LOGGER.info("Generated PlantUML diagram: {}", diagramDescription.getDescription());
while (matcher.find()) {
String fullTag = matcher.group(0);
String lang = matcher.group(1);
String code = "@startuml\n" + matcher.group(2);

String imageUrl = "/api/v1/session/" + context.threadId() + "/" + fileName;
String fileName = UUID.randomUUID() + "_plantuml.png";
Path subDirectoryPath = context.threadDirectory().resolve(context.threadId());
Path localFilePath = subDirectoryPath.resolve(fileName);

// Perform your Mustache template replacement here
String formattedContent = template.formatted(NO_LB_MARKER_START, imageUrl, code, NO_LB_MARKER_END);
content = content.replace(fullTag, formattedContent);
// Ensure the directory exists and is writable
try {
if (!Files.exists(subDirectoryPath)) {
Files.createDirectories(subDirectoryPath);
}
if (!Files.isWritable(subDirectoryPath)) {
throw new IOException("Directory is not writable: " + subDirectoryPath);
}
} catch (IOException ioEx) {
throw new RuntimeException(ioEx);
}

return content;
DiagramDescription diagramDescription = service.generateUmlDiagram(code,
localFilePath.toString());
LOGGER.info("Generated PlantUML diagram: {}", diagramDescription.getDescription());

String imageUrl = String.format(IMAGE_URL, context.threadId(), fileName);

// Perform your Mustache template replacement here
String formattedContent = TEMPLATE.formatted(NO_LB_MARKER_START, imageUrl, code,
NO_LB_MARKER_END);
content = content.replace(fullTag, formattedContent);
}

return content;
}

}
13 changes: 10 additions & 3 deletions frontend/src/components/assistant/AssistantElement.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import {useChatStore} from '@/store/chat-store';
import {useAssistants} from '@/composable/use-assistants';
import Assistant from '@/store/to/assistant';

export default {
name: 'AssistantElement',
Expand All @@ -33,11 +34,14 @@ export default {
};
},
props: {
assistant: Object,
assistant: Assistant,
},
computed: {
imageSrc() {
return this.assistants.getAssistantImageUrl(this.assistant.image_path);
if (this.assistant.image_path) {
return this.assistants.getAssistantImageUrl(this.assistant.image_path);
}
return '';
},
isShowAssistantImage() {
return !!this.assistant.image_path;
Expand Down Expand Up @@ -70,8 +74,11 @@ export default {
<template>
<v-card class="mx-auto" height="280" variant="elevated" width="200">
<div role="button" @click="onPersonaSelected">
<v-avatar :image="imageSrc" size="120">
<v-avatar v-if="imageSrc !== ''" :image="imageSrc" size="120">
</v-avatar>
<v-img v-else alt="Robot" class="mx-auto" max-height="120"
max-width="200" src="@/assets/robot.svg"></v-img>

<v-card-title>{{ assistant.name }}</v-card-title>
<v-card-text class="description">
{{ assistant.description }}
Expand Down
6 changes: 5 additions & 1 deletion frontend/src/components/chat/ChatMessage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {useChatStore} from '@/store/chat-store';
import Role from '@/store/to/role';
import ChatMessageTextToSpeech from '@/components/chat/ChatMessageTextToSpeech.vue';
import {useAssistants} from '@/composable/use-assistants';
import {ThreadMessage} from '@/store/to/thread';

export default {
name: 'ChatMessage',
Expand All @@ -33,7 +34,7 @@ export default {
return {};
},
props: {
message: Object,
message: ThreadMessage,
messageIndex: Number,
},
computed: {
Expand Down Expand Up @@ -96,6 +97,9 @@ export default {
await this.$refs.chatMessageAudioPlayerRef.playAudio();
},
getContent() {
if (this.chatStore.parsedMessages[this.message.id] !== undefined) {
return this.chatStore.parsedMessages[this.message.id];
}
return this.message.content[0].text.value;
},
getMessageStatus() {
Expand Down
7 changes: 0 additions & 7 deletions frontend/src/components/choice/ChoiceDesktop.vue
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,6 @@ export default defineComponent({
},

},
async mounted() {
try {
await this.assistants.syncAssistants();
} catch (error) {
this.appStore.handleError(error);
}
},
});
</script>

Expand Down
7 changes: 0 additions & 7 deletions frontend/src/components/choice/ChoiceMobile.vue
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,6 @@ export default defineComponent({
},

},
async mounted() {
try {
await this.assistants.syncAssistants();
} catch (error) {
this.appStore.handleError(error);
}
},
});
</script>

Expand Down
3 changes: 0 additions & 3 deletions frontend/src/components/choice/ChoiceView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,6 @@ export default {
// You can adjust the breakpoint here according to your needs

const isMobile = mobile.value;

console.log('DISPLAY: ', isMobile,
isMobile ? 'ChoiceMobile' : 'ChoiceDesktop');
return isMobile ? 'ChoiceMobile' : 'ChoiceDesktop';
});

Expand Down
4 changes: 1 addition & 3 deletions frontend/src/composable/use-assistants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ export function useAssistants() {

const streamRun = async (
assistantId: string, threadId: string, chunkUpdateCallback: () => void) => {
console.log('*** streamRun ', assistantId, threadId);

const debouncedUpdateCallback = debounce(chunkUpdateCallback, DEBOUNCE_TIME,
{maxWait: DEBOUNCE_MAXWAIT});
Expand Down Expand Up @@ -88,10 +87,8 @@ export function useAssistants() {
for (const part of parts) {
if (part.startsWith('event:')) {
currentEvent = part.substring(6);
console.log('--> event', currentEvent);
} else if (part.startsWith('data:')) {
const data = part.substring(5);
console.log('--> data', data);
processData(data, currentEvent, debouncedUpdateCallback);
currentEvent = '';
await sleep(DELAY_TIME);
Expand Down Expand Up @@ -458,6 +455,7 @@ export function useAssistants() {
const deleteThread = async (threadId: string) => {
console.log('Delete thread:', threadId);
await axios.delete(`/api/v1/threads/${threadId}`);
chatStore.newThread();
await retrieveThreads();
};

Expand Down
1 change: 1 addition & 0 deletions frontend/src/store/chat-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ export const useChatStore = defineStore('chat', {
this.currentStatusMessage = '';
this.currentStatusMessageType = '';
},

},

});

0 comments on commit 1d83692

Please sign in to comment.