✨Feat: 完成前端郭德纲教学卡片
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/tmc/langchaingo/llms"
|
||||
"github.com/tmc/langchaingo/outputparser"
|
||||
@@ -98,10 +99,20 @@ func CallWithAgentDefined[T any](llm llms.Model, ctx context.Context, topic stri
|
||||
llm,
|
||||
"用户正在学习Go语言和React框架,你是用户的助手。\n"+prompt,
|
||||
)
|
||||
|
||||
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
|
||||
if !strings.Contains(responseString, "```json") {
|
||||
responseString = "```json\n" + responseString + "```"
|
||||
}
|
||||
|
||||
fmt.Printf("AI: %s\n\n",responseString)
|
||||
|
||||
response, err = parse.Parse(responseString)
|
||||
if err != nil {
|
||||
fmt.Printf("Parse err: %v", err)
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
3. 语气轻松诙谐、接地气,但内容要准确专业
|
||||
4. 偶尔使用相声常用语,比如"您听好了"、"这就好比"、"想当年"、"您猜怎么着"
|
||||
5. 每讲完一个要点,可以用"这话怎么说呢?"来过渡
|
||||
6. 最后用"您记住了吗?下次要是有人问起来,您就把这么一通摆出来,准保让他对您刮目相看!"收尾
|
||||
|
||||
注意:
|
||||
- 不要过度夸张,保持内容的准确性和专业性
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/tmc/langchaingo/outputparser"
|
||||
)
|
||||
|
||||
// Parse parses the output of an LLM call.
|
||||
func (p outputparser.Defined[T)(T) Parse(text string) (T, error) {
|
||||
var target T
|
||||
|
||||
// Removes '```json' and '```' from the start and end of the text.
|
||||
const opening = "```json"
|
||||
const closing = "```"
|
||||
if text[:len(opening)] != opening || text[len(text)-len(closing):] != closing {
|
||||
return target, nil
|
||||
// return target, fmt.Errorf("input text should start with %s and end with %s", opening, closing)
|
||||
}
|
||||
parseableJSON := text[len(opening) : len(text)-len(closing)]
|
||||
if err := json.Unmarshal([]byte(parseableJSON), &target); err != nil {
|
||||
return target, fmt.Errorf("could not parse generated JSON: %w", err)
|
||||
}
|
||||
return target, nil
|
||||
}
|
||||
@@ -1,14 +1,16 @@
|
||||
import Card from "./components/Card";
|
||||
import Guodegang from "./components/Guodegang";
|
||||
import { Surface } from "@heroui/react";
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<>
|
||||
<Surface
|
||||
className="flex min-w-[320px] flex-col gap-3 rounded-3xl p-6"
|
||||
className="flex min-w-[320px] flex-row gap-4 rounded-3xl p-6 flex-wrap justify-center"
|
||||
variant="default"
|
||||
>
|
||||
<Card topic="React Hooks" />
|
||||
<Guodegang topic="React Hooks" />
|
||||
</Surface>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
import { Card } from "@heroui/react";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
interface GuodegangData {
|
||||
name: string;
|
||||
content: string;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
topic: string;
|
||||
}
|
||||
|
||||
export default function Guodegang({ topic }: Props) {
|
||||
const [data, setData] = useState<GuodegangData | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`http://localhost:8080/guodegang/${encodeURIComponent(topic)}`,
|
||||
);
|
||||
if (!response.ok) {
|
||||
throw new Error("API Error");
|
||||
}
|
||||
const result = await response.json();
|
||||
setData(result.message);
|
||||
setError(null);
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch data: ", error);
|
||||
setError("Failed to load data. Please try again.");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
fetchData();
|
||||
}, [topic]);
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="w-full p-4 sm:p-6 md:max-w-2xl lg:max-w-4xl mx-auto">
|
||||
<Card className="relative w-full max-w-2xl mx-auto bg-white shadow-xl rounded-2xl overflow-hidden border border-gray-100 p-8">
|
||||
<div className="text-center text-gray-600">Loading...</div>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<div className="w-full p-4 sm:p-6 md:max-w-2xl lg:max-w-4xl mx-auto">
|
||||
<Card className="relative w-full max-w-2xl mx-auto bg-white shadow-xl rounded-2xl overflow-hidden border border-gray-100 p-8">
|
||||
<div className="text-center text-red-600">{error}</div>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full p-4 sm:p-6 md:max-w-2xl lg:max-w-4xl mx-auto">
|
||||
<Card className="relative w-full max-w-2xl mx-auto bg-white shadow-xl rounded-2xl overflow-hidden border border-gray-100">
|
||||
<div className="absolute upper-0 right-0 -mr-2 -mb-2 pointer-events-none select-none">
|
||||
<span className="text-[10rem] opacity-80 blur-none">🎤</span>
|
||||
</div>
|
||||
|
||||
<div className="relative z-5">
|
||||
<div className="px-6 pt-6 pb-4">
|
||||
<Card.Title className="text-2xl font-bold text-gray-800 mb-2">
|
||||
{data!.name}
|
||||
</Card.Title>
|
||||
<div className="h-1 w-20 bg-gradient-to-r from-yellow-500 to-orange-500 rounded"></div>
|
||||
</div>
|
||||
|
||||
<Card.Description className="px-6 pb-6">
|
||||
<p className="text-gray-700 leading-relaxed whitespace-pre-line">
|
||||
{data!.content}
|
||||
</p>
|
||||
</Card.Description>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user